├── .gitignore ├── Gemfile ├── Gemfile.lock ├── Guardfile ├── Makefile ├── README.md ├── Rules ├── config.rb ├── content ├── 404.haml ├── about.haml ├── apple-touch-icon-57x57.png ├── apple-touch-icon-60x60.png ├── apple-touch-icon-72x72.png ├── apple-touch-icon-76x76.png ├── apple-touch-icon-precomposed.png ├── apple-touch-icon.png ├── assets │ └── css │ │ ├── _fonts.scss │ │ ├── _search.scss │ │ ├── _variables.scss │ │ └── styles.scss ├── favicon-16x16.png ├── favicon-196x196.png ├── favicon-32x32.png ├── favicon-96x96.png ├── favicon.ico ├── index.haml ├── search.haml ├── sitemap.haml └── tags │ └── index.haml ├── images ├── .gitkeep ├── audio_ready_icon.png ├── dvd_ready_icon.png ├── folder.png ├── hd_ready_icon.png ├── logos │ ├── blinkenlights │ │ └── folder-blinkenlights.jpg │ ├── broadcast │ │ └── sendezentrum │ │ │ └── sendezentrum.png │ ├── chaosradio │ │ └── video │ │ │ └── chaosradio-logo-transparent-300.png │ ├── conferences │ │ ├── camp1999 │ │ │ └── camprocket.png │ │ ├── camp2003 │ │ │ └── folder-camp-2003.png │ │ ├── camp2007 │ │ │ └── folder-camp-2007.jpg │ │ ├── camp2011 │ │ │ └── folder-camp-2011.png │ │ ├── camp2015 │ │ │ └── camp15-logo.png │ │ ├── chaoscologne │ │ │ └── 1c2 │ │ │ │ └── 1c2_logo.png │ │ ├── eh2014 │ │ │ └── logo-navbar.png │ │ ├── eh2015 │ │ │ └── eh15v4.png │ │ ├── fiffkon │ │ │ └── 2014 │ │ │ │ └── fiffkon14-logo.png │ │ ├── froscon │ │ │ ├── 2010 │ │ │ │ └── folder-froscon-2010.png │ │ │ ├── 2011 │ │ │ │ └── folder-froscon-2010.png │ │ │ ├── 2012 │ │ │ │ └── froscon.png │ │ │ ├── 2013 │ │ │ │ └── folder-froscon-2010.png │ │ │ ├── 2014 │ │ │ │ └── folder-froscon-2010.png │ │ │ └── 2015 │ │ │ │ └── froscon2015.png │ │ ├── har2009 │ │ │ └── folder-har-2009.png │ │ ├── mrmcd │ │ │ ├── mrmcd0x8 │ │ │ │ └── folder-mrmcd-2009.jpg │ │ │ ├── mrmcd101b │ │ │ │ └── folder-mrmcd-2006.png │ │ │ ├── mrmcd111b │ │ │ │ └── folder-mrmcd-2008.jpg │ │ │ ├── mrmcd13 │ │ │ │ └── mrmcd2013-logo.png │ │ │ ├── mrmcd14 │ │ │ │ └── mrmcd_14.png │ │ │ └── mrmcd15 │ │ │ │ ├── logo-export_mrmcd15.svg │ │ │ │ └── mrmcd_15.png │ │ ├── sigint09 │ │ │ └── folder-sigint-2009.png │ │ ├── sigint10 │ │ │ └── folder-sigint-2010.png │ │ ├── sigint12 │ │ │ └── folder-sigint-2012.jpg │ │ └── sigint13 │ │ │ └── folder-sigint-2013.png │ ├── congress │ │ ├── 2000 │ │ │ └── realmedia │ │ │ │ └── folder-17c3.png │ │ ├── 2001 │ │ │ └── folder-18c3.png │ │ ├── 2002 │ │ │ └── folder-19c3.png │ │ ├── 2003 │ │ │ └── folder-20c3.png │ │ ├── 2004 │ │ │ └── folder-21c3.png │ │ ├── 2005 │ │ │ └── folder-22c3.gif │ │ ├── 2006 │ │ │ └── folder-23c3.png │ │ ├── 2007 │ │ │ └── folder-24c3.jpg │ │ ├── 2008 │ │ │ └── folder-25c3.png │ │ ├── 2009 │ │ │ └── folder-26c3.jpg │ │ ├── 2010 │ │ │ └── folder-27c3.png │ │ ├── 2011 │ │ │ └── folder-28c3.png │ │ ├── 2012 │ │ │ └── folder-29c3.png │ │ ├── 2013 │ │ │ └── folder-30c3.png │ │ └── 2014 │ │ │ └── folder-2014.png │ ├── events │ │ ├── Panoptische_Prinzip │ │ │ └── logo.jpg │ │ ├── cryptocon │ │ │ └── 2015 │ │ │ │ └── cc15_logo_transparent.png │ │ ├── datenspuren │ │ │ ├── 2014 │ │ │ │ └── datenspuren2014-logo.png │ │ │ └── 2015 │ │ │ │ ├── ds15-logo-print.svg │ │ │ │ └── ds2015.png │ │ ├── gpn │ │ │ ├── gpn14 │ │ │ │ └── 80px-Gpn14_logo_navi.jpg.png │ │ │ └── gpn15 │ │ │ │ └── gpn15_logo.png │ │ ├── gpn10 │ │ │ └── 95px-GPN10-TShirt.png │ │ ├── hackover │ │ │ ├── 2013 │ │ │ │ └── hackover-2013.png │ │ │ ├── 2014 │ │ │ │ └── hackover-2014.png │ │ │ └── hackover-logo.png │ │ ├── netzpolitik │ │ │ ├── 10np │ │ │ │ └── 10np.png │ │ │ └── 11np │ │ │ │ └── 11np.png │ │ ├── vcfb │ │ │ └── 2014 │ │ │ │ ├── vcfb-logo-quer.png │ │ │ │ └── vcfb2015-logo.png │ │ ├── wauland │ │ │ └── whs_logo.png │ │ └── wie_werden_kriege_gemacht-koeln_2015 │ │ │ └── unknown.png │ ├── regional │ │ ├── berlin │ │ │ └── datengarten │ │ │ │ └── datengarten.png │ │ ├── c4 │ │ │ └── openchaos │ │ │ │ └── c4-logo.jpg │ │ └── cccac │ │ │ └── vortraege │ │ │ ├── cccac_logo_bw_kleiner.png │ │ │ └── logo.png │ └── unknown.png ├── miro-banner.png ├── promoted_bg.jpg ├── rss_logo.png ├── spinner.gif ├── tv-rausch.gif └── tv.png ├── layouts ├── browse-download-page.haml ├── browse-index.haml ├── browse-oembed-page.haml ├── browse-show-folder.haml ├── browse-show-page.haml ├── browse-show-tags.haml ├── default.haml └── partials │ ├── download.haml │ ├── embedshare.haml │ ├── folder-feeds.haml │ ├── footer.haml │ ├── header.haml │ ├── navbar.haml │ ├── promoted.haml │ ├── search.haml │ ├── videoplayer.haml │ └── videoplayer_js.haml ├── lib ├── data_source.rb ├── data_source │ ├── feed_builder.rb │ ├── item_builder.rb │ ├── location_pages.rb │ └── tag_pages.rb ├── default.rb ├── feeds.rb ├── feeds │ ├── broadcatching.xml.haml │ ├── broadcatching_generator.rb │ ├── helper.rb │ ├── newsfeed_generator.rb │ ├── podcast_generator.rb │ └── rdf_generator.rb ├── helpers.rb ├── helpers │ ├── application_helper.rb │ ├── logo_filter_helper.rb │ └── tagging_helper.rb ├── helpers_.rb ├── magnet_link_provider.rb ├── mime_type.rb └── models │ ├── conference.rb │ ├── event.rb │ ├── folder.rb │ ├── news.rb │ └── recording.rb ├── nanoc.yaml.example ├── settings.json ├── static ├── css │ ├── bigplay.png │ ├── bigplay.svg │ ├── controls.png │ ├── controls.svg │ ├── font-awesome.css │ ├── font-awesome.min.css │ ├── loading.gif │ └── mediaelementplayer.min.css ├── flashmediaelement.swf ├── fonts │ ├── FontAwesome.otf │ ├── bootstrap │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ ├── estre.eot │ ├── estre.otf │ ├── estre.svg │ ├── estre.ttf │ ├── estre.woff │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ └── fontawesome-webfont.woff └── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── handlebars.min-latest.js │ ├── jquery.min.js │ ├── mediaelement-and-player.min.js │ ├── purl.min.js │ └── search.js └── testdata.sql.gz /.gitignore: -------------------------------------------------------------------------------- 1 | tmp/ 2 | vendor/ 3 | output/ 4 | *sqlite3 5 | .ruby-version 6 | nanoc.yaml 7 | *sql 8 | *.log 9 | .idea 10 | .sass-cache 11 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'nanoc' 4 | gem 'haml' 5 | gem 'compass' 6 | gem 'bootstrap-sass' 7 | 8 | gem 'activerecord', '< 4.0' 9 | gem 'activesupport', '< 4.0' 10 | gem 'nokogiri' 11 | gem 'guard' 12 | gem 'guard-nanoc' 13 | gem 'adsf' 14 | 15 | platforms :jruby do 16 | gem 'activerecord-jdbcsqlite3-adapter' 17 | gem 'kramdown' 18 | end 19 | 20 | platforms :ruby do 21 | gem 'sqlite3' 22 | gem 'redcarpet' 23 | end 24 | 25 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activemodel (3.2.19) 5 | activesupport (= 3.2.19) 6 | builder (~> 3.0.0) 7 | activerecord (3.2.19) 8 | activemodel (= 3.2.19) 9 | activesupport (= 3.2.19) 10 | arel (~> 3.0.2) 11 | tzinfo (~> 0.3.29) 12 | activesupport (3.2.19) 13 | i18n (~> 0.6, >= 0.6.4) 14 | multi_json (~> 1.0) 15 | adsf (1.2.0) 16 | rack (>= 1.0.0) 17 | arel (3.0.3) 18 | bootstrap-sass (3.2.0.2) 19 | sass (~> 3.2) 20 | builder (3.0.4) 21 | celluloid (0.16.0) 22 | timers (~> 4.0.0) 23 | chunky_png (1.3.1) 24 | coderay (1.1.0) 25 | colored (1.2) 26 | compass (1.0.1) 27 | chunky_png (~> 1.2) 28 | compass-core (~> 1.0.1) 29 | compass-import-once (~> 1.0.5) 30 | rb-fsevent (>= 0.9.3) 31 | rb-inotify (>= 0.9) 32 | sass (>= 3.3.13, < 3.5) 33 | compass-core (1.0.1) 34 | multi_json (~> 1.0) 35 | sass (>= 3.3.0, < 3.5) 36 | compass-import-once (1.0.5) 37 | sass (>= 3.2, < 3.5) 38 | cri (2.6.1) 39 | colored (~> 1.2) 40 | ffi (1.9.3) 41 | formatador (0.2.5) 42 | guard (2.6.1) 43 | formatador (>= 0.2.4) 44 | listen (~> 2.7) 45 | lumberjack (~> 1.0) 46 | pry (>= 0.9.12) 47 | thor (>= 0.18.1) 48 | guard-nanoc (1.0.2) 49 | guard (>= 1.8.0) 50 | nanoc (>= 3.6.3) 51 | haml (4.0.5) 52 | tilt 53 | hitimes (1.2.2) 54 | i18n (0.6.11) 55 | listen (2.7.9) 56 | celluloid (>= 0.15.2) 57 | rb-fsevent (>= 0.9.3) 58 | rb-inotify (>= 0.9) 59 | lumberjack (1.0.9) 60 | method_source (0.8.2) 61 | mini_portile (0.6.0) 62 | multi_json (1.10.1) 63 | nanoc (3.7.3) 64 | cri (~> 2.3) 65 | nokogiri (1.6.3.1) 66 | mini_portile (= 0.6.0) 67 | pry (0.10.1) 68 | coderay (~> 1.1.0) 69 | method_source (~> 0.8.1) 70 | slop (~> 3.4) 71 | rack (1.5.2) 72 | rb-fsevent (0.9.4) 73 | rb-inotify (0.9.5) 74 | ffi (>= 0.5.0) 75 | redcarpet (3.1.2) 76 | sass (3.4.5) 77 | slop (3.6.0) 78 | sqlite3 (1.3.9) 79 | thor (0.19.1) 80 | tilt (2.0.1) 81 | timers (4.0.1) 82 | hitimes 83 | tzinfo (0.3.41) 84 | 85 | PLATFORMS 86 | ruby 87 | 88 | DEPENDENCIES 89 | activerecord (< 4.0) 90 | activerecord-jdbcsqlite3-adapter 91 | activesupport (< 4.0) 92 | adsf 93 | bootstrap-sass 94 | compass 95 | guard 96 | guard-nanoc 97 | haml 98 | kramdown 99 | nanoc 100 | nokogiri 101 | redcarpet 102 | sqlite3 103 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard 'nanoc' do 2 | watch 'nanoc.yaml' 3 | watch 'Rules' 4 | watch %r{\A(content|layouts|lib|static)/.*\z} 5 | ignore %r{(?:4913)$} 6 | notification :off 7 | end 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: 3 | git pull 4 | FAST_NANOC=1 nanoc co 5 | 6 | full: 7 | rm -fr tmp/cache 8 | rm /srv/www/media.ccc.de/output/index.html 9 | git pull 10 | nanoc co 11 | 12 | clean: 13 | rm -fr /srv/www/media.ccc.de/output/* 14 | rm -fr tmp/cache 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # media-frontend 2 | 3 | media.ccc.de webfrontend 4 | 5 | ## Install 6 | 7 | ### Ruby Version 8 | 9 | ruby 2.1 10 | 11 | ### Instructions 12 | 13 | The logo filter requires graphicmagic 14 | 15 | aptitude install graphicsmagick 16 | 17 | Install required ruby packages with bundler: 18 | 19 | gem install bundler 20 | bundle install 21 | 22 | 23 | Create config file 24 | 25 | cp nanoc.yaml.example nanoc.yaml 26 | 27 | 28 | ### Database Creation 29 | 30 | Import a database dump 31 | 32 | zcat testdata.sql.gz | sqlite3 development.sqlite3 33 | 34 | ## Nanoc 35 | 36 | [Nanoc](http://nanoc.ws) is a static site generator 37 | 38 | ### Compile static pages 39 | 40 | nanoc compile 41 | 42 | ### Start a webserver to view pages in a browser 43 | 44 | nanoc view 45 | 46 | ### Watch output directory for changes 47 | 48 | guard 49 | 50 | # JRuby 51 | 52 | export JRUBY_OPTS="--2.0 -J-Xmn512m -J-Xms2048m -J-Xmx2048m -J-server" 53 | 54 | 55 | ~/.jrubyrc 56 | 57 | compat.version=2.0 58 | -------------------------------------------------------------------------------- /Rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | unless defined? LOADED_DEFAULT_CONFIG 4 | LOADED_DEFAULT_CONFIG = true 5 | require 'compass' 6 | Compass.add_project_configuration 'config.rb' 7 | end 8 | 9 | # A few helpful tips about the Rules file: 10 | # 11 | # * The string given to #compile and #route are matching patterns for 12 | # identifiers--not for paths. Therefore, you can’t match on extension. 13 | # 14 | # * The order of rules is important: for each item, only the first matching 15 | # rule is applied. 16 | # 17 | # * Item identifiers start and end with a slash (e.g. “/about/” for the file 18 | # “content/about.html”). To select all children, grandchildren, … of an 19 | # item, use the pattern “/about/*/”; “/about/*” will also select the parent, 20 | # because “*” matches zero or more characters. 21 | 22 | compile '/browse/*' do 23 | if item[:layout].present? 24 | layout item[:layout] 25 | else 26 | nil 27 | end 28 | end 29 | 30 | compile 'sitemap' do 31 | filter :haml 32 | end 33 | 34 | route 'sitemap' do 35 | item.identifier.chop + '.xml' 36 | end 37 | 38 | route '/images/logos/*' do 39 | item.identifier.chop.chomp(item[:extension]) + 'png' 40 | end 41 | 42 | compile '/images/logos/*' do 43 | if item.binary? 44 | filter :logo 45 | end 46 | end 47 | 48 | # / 49 | compile '*' do 50 | unless item.binary? 51 | case item[:extension] 52 | when /scss/ 53 | filter :sass, Compass.sass_engine_options 54 | when 'haml' 55 | filter :haml, { :ugly => true, format: :html5 } 56 | layout 'default' 57 | else 58 | nil 59 | end 60 | end 61 | end 62 | 63 | # 64 | # Routes 65 | # 66 | 67 | # Assets 68 | route '/assets/**/_*' do 69 | # _mixed.scss 70 | nil 71 | end 72 | 73 | route '/assets/css/*/' do 74 | if item[:extension] == 'scss' 75 | item.identifier.chop + '.css' 76 | else 77 | item.identifier.chop 78 | end 79 | end 80 | 81 | passthrough '/assets/*' 82 | passthrough '/images/*' 83 | 84 | # AR datasource 85 | route '/browse/*' do 86 | if %w{browse-show-page browse-download-page browse-oembed-page browse-show-tags}.include? item[:layout] 87 | item.identifier.chop + '.' + 'html' 88 | elsif %w{rss xml}.include? item[:extension] 89 | # podcast.xml 90 | item.identifier.chop + '.' + item[:extension] 91 | else 92 | item.identifier + 'index.html' 93 | end 94 | end 95 | 96 | # Content 97 | route '*' do 98 | if item.binary? 99 | item.identifier.chop + '.' + item[:extension] 100 | elsif %w{/about/ /404/}.include? item.identifier 101 | # HAML pages in root except index.html 102 | item.identifier.chop + '.html' 103 | elsif %w{xml rdf atom}.include? item[:extension] 104 | # atom, xml or rdf feeds 105 | item.identifier.chop + '.' + item[:extension] 106 | else 107 | item.identifier + 'index.html' 108 | end 109 | end 110 | 111 | layout '*', :haml, {:ugly => true, format: :html5} 112 | -------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | # Require any additional compass plugins here. 2 | 3 | require 'bootstrap-sass' 4 | 5 | # Set this to the root of your project when deployed: 6 | http_path = "/" 7 | project_path = "." 8 | css_dir = "output/assets/css" 9 | sass_dir = "content/assets/css" 10 | images_dir = "output/images" 11 | 12 | # when using SCSS: 13 | sass_options = { 14 | :syntax => :scss 15 | } 16 | 17 | # You can select your preferred output style here (can be overridden via the command line): 18 | output_style = :compressed 19 | 20 | # To enable relative paths to assets via compass helper functions. Uncomment: 21 | relative_assets = true 22 | 23 | # To disable debugging comments that display the original location of your selectors. Uncomment: 24 | # line_comments = false 25 | -------------------------------------------------------------------------------- /content/404.haml: -------------------------------------------------------------------------------- 1 | --- 2 | title: 404 - Page not found 3 | --- 4 | 5 | = render 'partials/search', :title => '404 - Page not found' 6 | -------------------------------------------------------------------------------- /content/about.haml: -------------------------------------------------------------------------------- 1 | --- 2 | title: about media.ccc.de 3 | --- 4 | %script(src="/assets/js/handlebars.min-latest.js") 5 | 6 | %div.container 7 | 8 | %h1 About media.ccc.de 9 | 10 | %p 11 | This site offers a wide variety of video and audio material distributed by the Chaos Computer Club provided in native formats (usually MPEG and/or Vorbis families) for online viewing. Older, archived recordings might require propritary players. The media files on this site can also be downloaded for offline consumption. 12 | 13 | %p 14 | If you are anyhow related to the Chaos Computer Club and would like us to convert and publish your video material on this website, feel free to contact us. 15 | 16 | Whilst we hope you find the provided video material interesting and informative we can give no assurances or warranty regarding its quality. The opinions expressed in the video material do not necessarily state or reflect those of the Chaos Computer Club. 17 | 18 | %b Contact: 19 | %a{href: 'mailto:media@koeln.ccc.de'} media@koeln.ccc.de 20 | 21 | %h2 Licenses 22 | 23 | The license displayed in the actual video file applies. If there is no license encoded in the video file we suggest you ask the 24 | organizers of the recordings event. 25 | 26 | %h2 Privacy Policy 27 | 28 | %p 29 | While browsing through the website normally we do not save any information wich could be used to identify a person. The log files are anonymized before they are saved and we do not have a de-anonymized version of the them. The anonymized log-files may be used to plot usage statistics. 30 | 31 | The following data is collected and saved for an undefined duration: 32 | 33 | %ul 34 | %li Date and time, 35 | %li the visited pages, 36 | %li status codes the webserver answered with, 37 | %li your browser and operating system, 38 | %li and the referring URL 39 | 40 | %p 41 | If a connection to port 80 fails, an error log will be created. It contains the IP address of the host causing the error and the website containing the faulty hyperlink. This error log will only be used to fix the error and will not be used in any other way. 42 | 43 | %p 44 | Video and audio files are often provided by mirrors and are not covered by this policy. 45 | 46 | %h2 cdn.media.ccc.de 47 | 48 | %p 49 | :markdown 50 | The website is basically a frontend for all files stored on [cdn.media.ccc.de](//cdn.media.ccc.de). 51 | If you'd rather use a torrent you can append '.torrent' to any large file, this will provide a torrent with 52 | http seeds appropiate for your location. 53 | 54 | %h3 Current Mirrors 55 | 56 | #status 57 | 58 | %h2 Apps 59 | 60 | %ul 61 | %li 62 | %a{href: 'http://addons.xbmc.org/show/plugin.video.media-ccc-de/'} Kodi/XBMC plugin 63 | %li 64 | %a{href: 'https://github.com/cccc/MediaCCC.bundle'} Plex plugin (not released yet) 65 | 66 | %h2 Bug reports and feature requests 67 | %p 68 | Please use the 69 | %a{href: 'https://github.com/voc/media-frontend/issues'} issue tracker 70 | on github to let us know about errors or ideas to improve 71 | %a{href: '//media.ccc.de'} media.ccc.de 72 | \. The latest source code version of this platform is also hosted on 73 | %a{href: 'https://github.com/voc/media-frontend'} github 74 | and ready to expect your pull-requests. 75 | 76 | %h2 Imprint 77 | 78 | %p 79 | :markdown 80 | Please see [ccc.de](//ccc.de/de/imprint). 81 | 82 | %script#status-template{type: 'text/x-handlebars-template'} 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | {{#each mirrors}} 91 | {{#if this.status_baseurl}} 92 | 93 | {{else}} 94 | 95 | {{/if}} 96 | 97 | 98 | 99 | 100 | 101 | {{/each}} 102 |
NameLocationLast ScanFiles
{{this.identifier}}{{this.region}}/{{this.country}}{{this.last_scan}}{{this.nfiles}}
103 | 104 | :javascript 105 | $(document).ready(function() { 106 | var source = $('#status-template').html(); 107 | var template = Handlebars.compile(source); 108 | var target = $('#status'); 109 | $.get("//api.media.ccc.de/public/mirrors", function(data,status,xhr){ 110 | var html = template(data); 111 | target.html(html); 112 | }); 113 | }); 114 | 115 | -------------------------------------------------------------------------------- /content/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /content/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /content/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /content/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /content/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /content/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/apple-touch-icon.png -------------------------------------------------------------------------------- /content/assets/css/_fonts.scss: -------------------------------------------------------------------------------- 1 | /* font Estrangelo Edessa */ 2 | @font-face { 3 | font-family: 'Estrangelo Edessa'; 4 | src: url('../fonts/estre.eot'); 5 | font-weight: normal; 6 | font-style: normal; 7 | } 8 | @font-face { 9 | font-family: 'Estrangelo Edessa'; 10 | src: url('../fonts/estre.otf') format('opentype'); 11 | font-weight: normal; 12 | font-style: normal; 13 | } 14 | @font-face { 15 | font-family: 'Estrangelo Edessa'; 16 | src: url('../fonts/estre.ttf') format('truetype'), 17 | url('../fonts/estre.woff') format('woff'), 18 | url('../fonts/estre.svg') format('svg'); 19 | font-weight: normal; 20 | font-style: normal; 21 | } -------------------------------------------------------------------------------- /content/assets/css/_search.scss: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | 3 | .search { 4 | padding-bottom: 50px; 5 | 6 | form { 7 | margin-bottom: 30px; 8 | } 9 | 10 | input.text { 11 | outline: none; 12 | float: left; 13 | 14 | padding: 6px 12px; 15 | font-size: 14px; 16 | line-height: 1.428571429; 17 | 18 | vertical-align: middle; 19 | width: 50%; 20 | height: 28px; 21 | border: 1px solid #ccc; 22 | } 23 | 24 | button { 25 | border: 1px solid #ccc; 26 | height: 28px; 27 | } 28 | 29 | .results { 30 | &.initial { 31 | display: none; 32 | } 33 | 34 | .template { display: none; } 35 | } 36 | 37 | .paging { 38 | display: none; 39 | overflow: hidden; 40 | margin: 50px 0 0 150px; 41 | 42 | @media all and (max-width: $container-desktop) { 43 | margin-left: 0 !important; 44 | padding-left: 0 !important; 45 | } 46 | 47 | &.visible { 48 | display: block; 49 | } 50 | 51 | li { 52 | display: block; 53 | text-align: center; 54 | float: left; 55 | list-style-type: none; 56 | font-size: 18px; 57 | } 58 | 59 | li.page a { 60 | width: 1.2em; 61 | display: block; 62 | text-decoration: none; 63 | 64 | &:hover .number { text-decoration: underline; } 65 | } 66 | 67 | .postix { 68 | padding-left: 4px; 69 | } 70 | 71 | .next, .prev { 72 | visibility: hidden; 73 | &.visible { visibility: visible; } 74 | } 75 | .next { margin-left: 30px; } 76 | .prev { margin-right: 30px; } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /content/assets/css/_variables.scss: -------------------------------------------------------------------------------- 1 | @import "bootstrap/variables"; 2 | 3 | // Override Bootstrap variables here (defaults from bootstrap-sass v3.1.1.1): 4 | 5 | // a flag to toggle asset pipeline / compass integration 6 | // defaults to true if twbs-font-path function is present (no function => twbs-font-path('') parsed as string == right side) 7 | // in Sass 3.3 this can be improved with: function-exists(twbs-font-path) 8 | // $bootstrap-sass-asset-helper: (twbs-font-path("") != unquote('twbs-font-path("")')) 9 | // 10 | // Variables 11 | // -------------------------------------------------- 12 | 13 | //== Colors 14 | // 15 | //## Gray and brand colors for use across Bootstrap. 16 | 17 | // $gray-darker: lighten(#000, 13.5%) // #222 18 | // $gray-dark: lighten(#000, 20%) // #333 (buttons & header) 19 | // $gray: lighten(#000, 33.5%) // #555 20 | // $gray-light: lighten(#000, 60%) // #999 21 | // $gray-lighter: lighten(#000, 93.5%) // #eee 22 | 23 | $brand-primary: #d87500; // orange 24 | $transparent-white: rgba(255, 255, 255, 0.3); 25 | // $brand-success: #5cb85c 26 | // $brand-info: #5bc0de 27 | // $brand-warning: #f0ad4e 28 | // $brand-danger: #d9534f 29 | 30 | //== Scaffolding 31 | // 32 | //## Settings for some of the most global styles. 33 | 34 | //* Background color for ``. 35 | // $body-bg: #fff 36 | $body-bg: #fff; 37 | //* Global text color on ``. 38 | $text-color: #000; 39 | 40 | //* Global textual link color. 41 | $link-color: $brand-primary; 42 | //* Link hover color set via `darken()` function. 43 | $link-hover-color: darken($link-color, 15%); 44 | 45 | //== Typography 46 | // 47 | //## Font, line-height, and color for body text, headings, and more. 48 | 49 | $font-family-sans-serif: "Estrangelo Edessa", "Helvetica Neue", Helvetica, Arial, sans-serif; 50 | // $font-family-serif: Georgia, "Times New Roman", Times, serif 51 | //* Default monospace fonts for ``, ``, and `
`.
 52 | // $font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace
 53 | $font-family-base:        $font-family-sans-serif;
 54 | //$font-family: "Droid Sans",Arial,"Trebuchet MS",sans-serif;
 55 | 
 56 | $font-size-base:          14px;
 57 | $font-size-large:         ceil(($font-size-base * 1.7)); // ~24px
 58 | // $font-size-small:         ceil(($font-size-base * 0.85)) // ~12px
 59 | 
 60 | $font-size-h1:            floor(($font-size-base * 3)); // ~42px
 61 | $font-size-h2:            floor(($font-size-base * 2.15)); // ~30px
 62 | // $font-size-h3:            ceil(($font-size-base * 1.7)) // ~24px
 63 | // $font-size-h4:            ceil(($font-size-base * 1.25)) // ~18px
 64 | // $font-size-h5:            $font-size-base
 65 | // $font-size-h6:            ceil(($font-size-base * 0.85)) // ~12px
 66 | 
 67 | //* Unit-less `line-height` for use in components like buttons.
 68 | $line-height-base:        1.2;
 69 | //* Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
 70 | $line-height-computed:    floor(($font-size-base * $line-height-base));
 71 | 
 72 | //* By default, this inherits from the ``.
 73 | // $headings-font-family:    inherit
 74 | // $headings-font-weight:    500
 75 | // $headings-line-height:    1.1
 76 | $headings-color:          $gray;
 77 | 
 78 | //== Iconography
 79 | //
 80 | //## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
 81 | 
 82 | //* Load fonts from this directory.
 83 | $icon-font-path: "../fonts/";
 84 | //* File name for all font files.
 85 | $icon-font-name: "fontawesome-webfont";
 86 | //* Element ID within SVG icon file.
 87 | $icon-font-svg-id: "fontawesomeregular";
 88 | 
 89 | //== Components
 90 | //
 91 | //## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
 92 | 
 93 | $padding-base-vertical:     4px;
 94 | // $padding-base-horizontal:   12px
 95 | 
 96 | // $padding-large-vertical:    10px
 97 | // $padding-large-horizontal:  16px
 98 | 
 99 | // $padding-small-vertical:    5px
100 | // $padding-small-horizontal:  10px
101 | 
102 | // $padding-xs-vertical:       1px
103 | // $padding-xs-horizontal:     5px
104 | 
105 | // $line-height-large:         1.33
106 | // $line-height-small:         1.5
107 | 
108 | $border-radius-base:        0;
109 | $border-radius-large:       0;
110 | $border-radius-small:       0;
111 | 
112 | //* Global color for active items (e.g., navs or dropdowns).
113 | // $component-active-color:    #fff
114 | //* Global background color for active items (e.g., navs or dropdowns).
115 | // $component-active-bg:       $brand-primary
116 | 
117 | //* Width of the `border` for generating carets that indicator dropdowns.
118 | // $caret-width-base:          4px
119 | //* Carets increase slightly in size for larger components.
120 | // $caret-width-large:         5px
121 | 
122 | //== Tables
123 | //
124 | //## Customizes the `.table` component with basic values, each used across all table variations.
125 | 
126 | //* Padding for ``s and ``s.
127 | // $table-cell-padding:            8px
128 | //* Padding for cells in `.table-condensed`.
129 | // $table-condensed-cell-padding:  5px
130 | 
131 | //* Default background color used for all tables.
132 | // $table-bg:                      transparent
133 | //* Background color used for `.table-striped`.
134 | // $table-bg-accent:               #f9f9f9
135 | //* Background color used for `.table-hover`.
136 | // $table-bg-hover:                #f5f5f5
137 | // $table-bg-active:               $table-bg-hover
138 | 
139 | //* Border color for table and cell borders.
140 | // $table-border-color:            #ddd
141 | 
142 | //== Buttons
143 | //
144 | //## For each of Bootstrap's buttons, define text, background and border color.
145 | 
146 | // $btn-font-weight:                normal
147 | 
148 | $btn-default-color:              $gray-dark;
149 | $btn-default-bg:                 #fff;
150 | $btn-default-border:             #fff;
151 | 
152 | $btn-primary-color:              #fff;
153 | $btn-primary-bg:                 $gray-dark;
154 | $btn-primary-border:             $gray-dark;
155 | 
156 | // $btn-success-color:              #fff
157 | // $btn-success-bg:                 $brand-success
158 | // $btn-success-border:             darken($btn-success-bg, 5%)
159 | 
160 | // $btn-info-color:                 #fff
161 | // $btn-info-bg:                    $brand-info
162 | // $btn-info-border:                darken($btn-info-bg, 5%)
163 | 
164 | // $btn-warning-color:              #fff
165 | // $btn-warning-bg:                 $brand-warning
166 | // $btn-warning-border:             darken($btn-warning-bg, 5%)
167 | 
168 | // $btn-danger-color:               #fff
169 | // $btn-danger-bg:                  $brand-danger
170 | // $btn-danger-border:              darken($btn-danger-bg, 5%)
171 | 
172 | // $btn-link-disabled-color:        $gray-light
173 | 
174 | //== Forms
175 | //
176 | //##
177 | 
178 | //* `` background color
179 | // $input-bg:                       #fff
180 | //* `` background color
181 | // $input-bg-disabled:              $gray-lighter
182 | 
183 | //* Text color for ``s
184 | // $input-color:                    $gray
185 | //* `` border color
186 | $input-border:                   transparent;
187 | //* `` border radius
188 | $input-border-radius: $border-radius-base;
189 | //* Border color for inputs on focus
190 | $input-border-focus:             $brand-primary;
191 | 
192 | //* Placeholder text color
193 | $input-color-placeholder:        $gray-light;
194 | 
195 | //* Default `.form-control` height
196 | $input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2);
197 | //* Large `.form-control` height
198 | // $input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2)
199 | //* Small `.form-control` height
200 | // $input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2)
201 | 
202 | // $legend-color:                   $gray-dark
203 | // $legend-border-color:            #e5e5e5
204 | 
205 | //* Background color for textual input addons
206 | // $input-group-addon-bg:           $gray-lighter
207 | //* Border color for textual input addons
208 | // $input-group-addon-border-color: $input-border
209 | 
210 | //== Dropdowns
211 | //
212 | //## Dropdown menu container and contents.
213 | 
214 | //* Background for the dropdown menu.
215 | // $dropdown-bg:                    #fff
216 | //* Dropdown menu `border-color`.
217 | // $dropdown-border:                rgba(0,0,0,.15)
218 | //* Dropdown menu `border-color` **for IE8**.
219 | // $dropdown-fallback-border:       #ccc
220 | //* Divider color for between dropdown items.
221 | // $dropdown-divider-bg:            #e5e5e5
222 | 
223 | //* Dropdown link text color.
224 | // $dropdown-link-color:            $gray-dark
225 | //* Hover color for dropdown links.
226 | // $dropdown-link-hover-color:      darken($gray-dark, 5%)
227 | //* Hover background for dropdown links.
228 | // $dropdown-link-hover-bg:         #f5f5f5
229 | 
230 | //* Active dropdown menu item text color.
231 | // $dropdown-link-active-color:     $component-active-color
232 | //* Active dropdown menu item background color.
233 | // $dropdown-link-active-bg:        $component-active-bg
234 | 
235 | //* Disabled dropdown menu item background color.
236 | // $dropdown-link-disabled-color:   $gray-light
237 | 
238 | //* Text color for headers within dropdown menus.
239 | // $dropdown-header-color:          $gray-light
240 | 
241 | // Note: Deprecated $dropdown-caret-color as of v3.1.0
242 | // $dropdown-caret-color:           #000
243 | 
244 | //-- Z-index master list
245 | //
246 | // Warning: Avoid customizing these values. They're used for a bird's eye view
247 | // of components dependent on the z-axis and are designed to all work together.
248 | //
249 | // Note: These variables are not generated into the Customizer.
250 | 
251 | // $zindex-navbar:            1000
252 | // $zindex-dropdown:          1000
253 | // $zindex-popover:           1060
254 | // $zindex-tooltip:           1070
255 | // $zindex-navbar-fixed:      1030
256 | // $zindex-modal-background:  1040
257 | // $zindex-modal:             1050
258 | 
259 | //== Media queries breakpoints
260 | //
261 | //## Define the breakpoints at which your layout will change, adapting to different screen sizes.
262 | 
263 | // Extra small screen / phone
264 | // Note: Deprecated $screen-xs and $screen-phone as of v3.0.1
265 | // Note: Deprecated $screen-xs-min as of v3.2.0
266 | // $screen-xs:                  480px
267 | // $screen-xs-min:              $screen-xs
268 | // $screen-phone:               $screen-xs-min
269 | 
270 | // Small screen / tablet
271 | // Note: Deprecated $screen-sm and $screen-tablet as of v3.0.1
272 | $screen-sm:                  450px;
273 | $screen-sm-min:              $screen-sm;
274 | $screen-tablet:              $screen-sm-min;
275 | 
276 | // Medium screen / desktop
277 | // Note: Deprecated $screen-md and $screen-desktop as of v3.0.1
278 | $screen-md:                  960px;
279 | $screen-md-min:              $screen-md;
280 | $screen-desktop:             $screen-md-min;
281 | 
282 | // Large screen / wide desktop
283 | // Note: Deprecated $screen-lg and $screen-lg-desktop as of v3.0.1
284 | $screen-lg:                  1200px;
285 | $screen-lg-min:              $screen-lg;
286 | $screen-lg-desktop:          $screen-lg-min;
287 | 
288 | // So media queries don't overlap when required, provide a maximum
289 | $screen-xs-max:              ($screen-sm-min - 1);
290 | $screen-sm-max:              ($screen-md-min - 1);
291 | $screen-md-max:              ($screen-lg-min - 1);
292 | 
293 | //== Grid system
294 | //
295 | //## Define your custom responsive grid.
296 | 
297 | //* Number of columns in the grid.
298 | // $grid-columns:              12
299 | //* Padding between columns. Gets divided in half for the left and right.
300 | // $grid-gutter-width:         30px
301 | // Navbar collapse
302 | //* Point at which the navbar becomes uncollapsed.
303 | $grid-float-breakpoint:     0; //$screen-sm-min;
304 | //* Point at which the navbar begins collapsing.
305 | $grid-float-breakpoint-max: 0; //($grid-float-breakpoint - 1);
306 | 
307 | //== Container sizes
308 | //
309 | //## Define the maximum width of `.container` for different screen sizes.
310 | 
311 | // Small screen / tablet
312 | $container-tablet:             700px;
313 | //* For `$screen-sm-min` and up.
314 | $container-sm:                 $container-tablet;
315 | 
316 | // Medium screen / desktop
317 | $container-desktop:            700px;
318 | //* For `$screen-md-min` and up.
319 | $container-md:                 $container-desktop;
320 | 
321 | // Large screen / wide desktop
322 | $container-large-desktop:      700px;
323 | //* For `$screen-lg-min` and up.
324 | $container-lg:                 $container-large-desktop;
325 | 
326 | //== Navbar
327 | //
328 | //##
329 | 
330 | // Basics of a navbar
331 | $navbar-height:                    48px;
332 | $navbar-margin-bottom:             0;
333 | $navbar-border-radius:             $border-radius-base;
334 | // $navbar-padding-horizontal:        floor(($grid-gutter-width / 2))
335 | $navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2);
336 | // $navbar-collapse-max-height:       340px
337 | 
338 | // $navbar-default-color:             #777
339 | $navbar-default-bg:                $gray-dark;
340 | $navbar-default-border:            transparent;
341 | 
342 | // Navbar links
343 | $navbar-default-link-color:                $gray-dark;
344 | $navbar-default-link-hover-color:          $brand-primary;
345 | $navbar-default-link-hover-bg:             #fff;
346 | // $navbar-default-link-active-color:         #555
347 | // $navbar-default-link-active-bg:            darken($navbar-default-bg, 6.5%)
348 | // $navbar-default-link-disabled-color:       #ccc
349 | // $navbar-default-link-disabled-bg:          transparent
350 | 
351 | // Navbar brand label
352 | $navbar-default-brand-color:               #fff;
353 | $navbar-default-brand-hover-color:         $gray-lighter;
354 | // $navbar-default-brand-hover-bg:            transparent
355 | 
356 | // Navbar toggle
357 | // $navbar-default-toggle-hover-bg:           #ddd
358 | // $navbar-default-toggle-icon-bar-bg:        #888
359 | // $navbar-default-toggle-border-color:       #ddd
360 | 
361 | // Inverted navbar
362 | // Reset inverted navbar basics
363 | // $navbar-inverse-color:                      $gray-light
364 | // $navbar-inverse-bg:                         #222
365 | // $navbar-inverse-border:                     darken($navbar-inverse-bg, 10%)
366 | 
367 | // Inverted navbar links
368 | // $navbar-inverse-link-color:                 $gray-light
369 | // $navbar-inverse-link-hover-color:           #fff
370 | // $navbar-inverse-link-hover-bg:              transparent
371 | // $navbar-inverse-link-active-color:          $navbar-inverse-link-hover-color
372 | // $navbar-inverse-link-active-bg:             darken($navbar-inverse-bg, 10%)
373 | // $navbar-inverse-link-disabled-color:        #444
374 | // $navbar-inverse-link-disabled-bg:           transparent
375 | 
376 | // Inverted navbar brand label
377 | // $navbar-inverse-brand-color:                $navbar-inverse-link-color
378 | // $navbar-inverse-brand-hover-color:          #fff
379 | // $navbar-inverse-brand-hover-bg:             transparent
380 | 
381 | // Inverted navbar toggle
382 | // $navbar-inverse-toggle-hover-bg:            #333
383 | // $navbar-inverse-toggle-icon-bar-bg:         #fff
384 | // $navbar-inverse-toggle-border-color:        #333
385 | 
386 | //== Navs
387 | //
388 | //##
389 | 
390 | //=== Shared nav styles
391 | $nav-link-padding:                          0px 10px;
392 | $nav-link-hover-bg:                         #fff;
393 | 
394 | // $nav-disabled-link-color:                   $gray-light
395 | // $nav-disabled-link-hover-color:             $gray-light
396 | 
397 | // $nav-open-link-hover-color:                 #fff
398 | 
399 | //== Tabs
400 | // $nav-tabs-border-color:                     #ddd
401 | 
402 | // $nav-tabs-link-hover-border-color:          $gray-lighter
403 | 
404 | // $nav-tabs-active-link-hover-bg:             $body-bg
405 | // $nav-tabs-active-link-hover-color:          $gray
406 | // $nav-tabs-active-link-hover-border-color:   #ddd
407 | 
408 | // $nav-tabs-justified-link-border-color:            #ddd
409 | // $nav-tabs-justified-active-link-border-color:     $body-bg
410 | 
411 | //== Pills
412 | $nav-pills-border-radius:                   $border-radius-base;
413 | // $nav-pills-active-link-hover-bg:            $component-active-bg
414 | // $nav-pills-active-link-hover-color:         $component-active-color
415 | 
416 | //== Pagination
417 | //
418 | //##
419 | 
420 | // $pagination-color:                     $link-color
421 | // $pagination-bg:                        #fff
422 | // $pagination-border:                    #ddd
423 | 
424 | // $pagination-hover-color:               $link-hover-color
425 | // $pagination-hover-bg:                  $gray-lighter
426 | // $pagination-hover-border:              #ddd
427 | 
428 | // $pagination-active-color:              #fff
429 | // $pagination-active-bg:                 $brand-primary
430 | // $pagination-active-border:             $brand-primary
431 | 
432 | // $pagination-disabled-color:            $gray-light
433 | // $pagination-disabled-bg:               #fff
434 | // $pagination-disabled-border:           #ddd
435 | 
436 | //== Pager
437 | //
438 | //##
439 | 
440 | // $pager-bg:                             $pagination-bg
441 | // $pager-border:                         $pagination-border
442 | // $pager-border-radius:                  15px
443 | 
444 | // $pager-hover-bg:                       $pagination-hover-bg
445 | 
446 | // $pager-active-bg:                      $pagination-active-bg
447 | // $pager-active-color:                   $pagination-active-color
448 | 
449 | // $pager-disabled-color:                 $pagination-disabled-color
450 | 
451 | //== Jumbotron
452 | //
453 | //##
454 | 
455 | // $jumbotron-padding:              30px
456 | // $jumbotron-color:                inherit
457 | // $jumbotron-bg:                   $gray-lighter
458 | // $jumbotron-heading-color:        inherit
459 | // $jumbotron-font-size:            ceil(($font-size-base * 1.5))
460 | 
461 | //== Form states and alerts
462 | //
463 | //## Define colors for form feedback states and, by default, alerts.
464 | 
465 | // $state-success-text:             #3c763d
466 | // $state-success-bg:               #dff0d8
467 | // $state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%)
468 | 
469 | // $state-info-text:                #31708f
470 | // $state-info-bg:                  #d9edf7
471 | // $state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%)
472 | 
473 | // $state-warning-text:             #8a6d3b
474 | // $state-warning-bg:               #fcf8e3
475 | // $state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 5%)
476 | 
477 | // $state-danger-text:              #a94442
478 | // $state-danger-bg:                #f2dede
479 | // $state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 5%)
480 | 
481 | //== Tooltips
482 | //
483 | //##
484 | 
485 | //* Tooltip max width
486 | // $tooltip-max-width:           200px
487 | //* Tooltip text color
488 | // $tooltip-color:               #fff
489 | //* Tooltip background color
490 | // $tooltip-bg:                  #000
491 | // $tooltip-opacity:             .9
492 | 
493 | //* Tooltip arrow width
494 | // $tooltip-arrow-width:         5px
495 | //* Tooltip arrow color
496 | // $tooltip-arrow-color:         $tooltip-bg
497 | 
498 | //== Popovers
499 | //
500 | //##
501 | 
502 | //* Popover body background color
503 | // $popover-bg:                          #fff
504 | //* Popover maximum width
505 | // $popover-max-width:                   276px
506 | //* Popover border color
507 | // $popover-border-color:                rgba(0,0,0,.2)
508 | //* Popover fallback border color
509 | // $popover-fallback-border-color:       #ccc
510 | 
511 | //* Popover title background color
512 | // $popover-title-bg:                    darken($popover-bg, 3%)
513 | 
514 | //* Popover arrow width
515 | // $popover-arrow-width:                 10px
516 | //* Popover arrow color
517 | // $popover-arrow-color:                 #fff
518 | 
519 | //* Popover outer arrow width
520 | // $popover-arrow-outer-width:           ($popover-arrow-width + 1)
521 | //* Popover outer arrow color
522 | // $popover-arrow-outer-color:           rgba($popover-border-color, 0.05)
523 | //* Popover outer arrow fallback color
524 | // $popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%)
525 | 
526 | //== Labels
527 | //
528 | //##
529 | 
530 | //* Default label background color
531 | $label-default-bg:            $gray-dark;
532 | //* Primary label background color
533 | // $label-primary-bg:            $brand-primary
534 | //* Success label background color
535 | // $label-success-bg:            $brand-success
536 | //* Info label background color
537 | // $label-info-bg:               $brand-info
538 | //* Warning label background color
539 | // $label-warning-bg:            $brand-warning
540 | //* Danger label background color
541 | // $label-danger-bg:             $brand-danger
542 | 
543 | //* Default label text color
544 | // $label-color:                 #fff
545 | //* Default text color of a linked label
546 | // $label-link-hover-color:      #fff
547 | 
548 | //== Modals
549 | //
550 | //##
551 | 
552 | //* Padding applied to the modal body
553 | // $modal-inner-padding:         15px
554 | 
555 | //* Padding applied to the modal title
556 | // $modal-title-padding:         15px
557 | //* Modal title line-height
558 | // $modal-title-line-height:     $line-height-base
559 | 
560 | //* Background color of modal content area
561 | // $modal-content-bg:                             #fff
562 | //* Modal content border color
563 | // $modal-content-border-color:                   rgba(0,0,0,.2)
564 | //* Modal content border color **for IE8**
565 | // $modal-content-fallback-border-color:          #999
566 | 
567 | //* Modal backdrop background color
568 | // $modal-backdrop-bg:           #000
569 | //* Modal backdrop opacity
570 | // $modal-backdrop-opacity:      .5
571 | //* Modal header border color
572 | // $modal-header-border-color:   #e5e5e5
573 | //* Modal footer border color
574 | // $modal-footer-border-color:   $modal-header-border-color
575 | 
576 | // $modal-lg:                    900px
577 | // $modal-md:                    600px
578 | // $modal-sm:                    300px
579 | 
580 | //== Alerts
581 | //
582 | //## Define alert colors, border radius, and padding.
583 | 
584 | // $alert-padding:               15px
585 | $alert-border-radius:         $border-radius-base;
586 | // $alert-link-font-weight:      bold
587 | 
588 | // $alert-success-bg:            $state-success-bg
589 | // $alert-success-text:          $state-success-text
590 | // $alert-success-border:        $state-success-border
591 | 
592 | // $alert-info-bg:               $state-info-bg
593 | // $alert-info-text:             $state-info-text
594 | // $alert-info-border:           $state-info-border
595 | 
596 | // $alert-warning-bg:            $state-warning-bg
597 | // $alert-warning-text:          $state-warning-text
598 | // $alert-warning-border:        $state-warning-border
599 | 
600 | // $alert-danger-bg:             $state-danger-bg
601 | // $alert-danger-text:           $state-danger-text
602 | // $alert-danger-border:         $state-danger-border
603 | 
604 | //== Progress bars
605 | //
606 | //##
607 | 
608 | //* Background color of the whole progress component
609 | // $progress-bg:                 #f5f5f5
610 | //* Progress bar text color
611 | // $progress-bar-color:          #fff
612 | 
613 | //* Default progress bar color
614 | // $progress-bar-bg:             $brand-primary
615 | //* Success progress bar color
616 | // $progress-bar-success-bg:     $brand-success
617 | //* Warning progress bar color
618 | // $progress-bar-warning-bg:     $brand-warning
619 | //* Danger progress bar color
620 | // $progress-bar-danger-bg:      $brand-danger
621 | //* Info progress bar color
622 | // $progress-bar-info-bg:        $brand-info
623 | 
624 | //== List group
625 | //
626 | //##
627 | 
628 | //* Background color on `.list-group-item`
629 | // $list-group-bg:                 #fff
630 | //* `.list-group-item` border color
631 | // $list-group-border:             #ddd
632 | //* List group border radius
633 | // $list-group-border-radius:      $border-radius-base
634 | 
635 | //* Background color of single list items on hover
636 | // $list-group-hover-bg:           #f5f5f5
637 | //* Text color of active list items
638 | // $list-group-active-color:       $component-active-color
639 | //* Background color of active list items
640 | // $list-group-active-bg:          $component-active-bg
641 | //* Border color of active list elements
642 | // $list-group-active-border:      $list-group-active-bg
643 | //* Text color for content within active list items
644 | // $list-group-active-text-color:  lighten($list-group-active-bg, 40%)
645 | 
646 | //* Text color of disabled list items
647 | // $list-group-disabled-color:      $gray-light
648 | //* Background color of disabled list items
649 | // $list-group-disabled-bg:         $gray-lighter
650 | //* Text color for content within disabled list items
651 | // $list-group-disabled-text-color: $list-group-disabled-color
652 | 
653 | // $list-group-link-color:         #555
654 | // $list-group-link-hover-color:   $list-group-link-color
655 | // $list-group-link-heading-color: #333
656 | 
657 | //== Panels
658 | //
659 | //##
660 | 
661 | // $panel-bg:                    #fff
662 | // $panel-body-padding:          15px
663 | // $panel-heading-padding:       10px 15px
664 | // $panel-footer-padding:        $panel-heading-padding
665 | $panel-border-radius:         $border-radius-base;
666 | 
667 | //* Border color for elements within panels
668 | // $panel-inner-border:          #ddd
669 | // $panel-footer-bg:             #f5f5f5
670 | 
671 | // $panel-default-text:          $gray-dark
672 | // $panel-default-border:        #ddd
673 | // $panel-default-heading-bg:    #f5f5f5
674 | 
675 | // $panel-primary-text:          #fff
676 | // $panel-primary-border:        $brand-primary
677 | // $panel-primary-heading-bg:    $brand-primary
678 | 
679 | // $panel-success-text:          $state-success-text
680 | // $panel-success-border:        $state-success-border
681 | // $panel-success-heading-bg:    $state-success-bg
682 | 
683 | // $panel-info-text:             $state-info-text
684 | // $panel-info-border:           $state-info-border
685 | // $panel-info-heading-bg:       $state-info-bg
686 | 
687 | // $panel-warning-text:          $state-warning-text
688 | // $panel-warning-border:        $state-warning-border
689 | // $panel-warning-heading-bg:    $state-warning-bg
690 | 
691 | // $panel-danger-text:           $state-danger-text
692 | // $panel-danger-border:         $state-danger-border
693 | // $panel-danger-heading-bg:     $state-danger-bg
694 | 
695 | //== Thumbnails
696 | //
697 | //##
698 | 
699 | //* Padding around the thumbnail image
700 | // $thumbnail-padding:           4px
701 | //* Thumbnail background color
702 | // $thumbnail-bg:                $body-bg
703 | //* Thumbnail border color
704 | $thumbnail-border:            none;
705 | //* Thumbnail border radius
706 | $thumbnail-border-radius:     $border-radius-base;
707 | 
708 | //* Custom text color for thumbnail captions
709 | // $thumbnail-caption-color:     $text-color
710 | //* Padding around the thumbnail caption
711 | // $thumbnail-caption-padding:   9px
712 | 
713 | //== Wells
714 | //
715 | //##
716 | 
717 | // $well-bg:                     #f5f5f5
718 | // $well-border:                 darken($well-bg, 7%)
719 | 
720 | //== Badges
721 | //
722 | //##
723 | 
724 | // $badge-color:                 #fff
725 | //* Linked badge text color on hover
726 | // $badge-link-hover-color:      #fff
727 | // $badge-bg:                    $gray-light
728 | 
729 | //* Badge text color in active nav link
730 | // $badge-active-color:          $link-color
731 | //* Badge background color in active nav link
732 | // $badge-active-bg:             #fff
733 | 
734 | // $badge-font-weight:           bold
735 | // $badge-line-height:           1
736 | // $badge-border-radius:         10px
737 | 
738 | //== Breadcrumbs
739 | //
740 | //##
741 | 
742 | // $breadcrumb-padding-vertical:   8px
743 | // $breadcrumb-padding-horizontal: 15px
744 | //* Breadcrumb background color
745 | $breadcrumb-bg:                 none;
746 | //* Breadcrumb text color
747 | $breadcrumb-color:              #fff;
748 | //* Text color of current page in the breadcrumb
749 | $breadcrumb-active-color:       $brand-primary;
750 | //* Textual separator for between breadcrumb elements
751 | $breadcrumb-separator:          "\f054"
752 | 
753 | //== Carousel
754 | //
755 | //##
756 | 
757 | // $carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6)
758 | 
759 | // $carousel-control-color:                      #fff
760 | // $carousel-control-width:                      15%
761 | // $carousel-control-opacity:                    .5
762 | // $carousel-control-font-size:                  20px
763 | 
764 | // $carousel-indicator-active-bg:                #fff
765 | // $carousel-indicator-border-color:             #fff
766 | 
767 | // $carousel-caption-color:                      #fff
768 | 
769 | //== Close
770 | //
771 | //##
772 | 
773 | // $close-font-weight:           bold
774 | // $close-color:                 #000
775 | // $close-text-shadow:           0 1px 0 #fff
776 | 
777 | //== Code
778 | //
779 | //##
780 | 
781 | // $code-color:                  #c7254e
782 | // $code-bg:                     #f9f2f4
783 | 
784 | // $kbd-color:                   #fff
785 | // $kbd-bg:                      #333
786 | 
787 | // $pre-bg:                      #f5f5f5
788 | // $pre-color:                   $gray-dark
789 | // $pre-border-color:            #ccc
790 | // $pre-scrollable-max-height:   340px
791 | 
792 | //== Type
793 | //
794 | //##
795 | 
796 | //* Text muted color
797 | // $text-muted:                  $gray-light
798 | //* Abbreviations and acronyms border color
799 | // $abbr-border-color:           $gray-light
800 | //* Headings small color
801 | // $headings-small-color:        $gray-light
802 | //* Blockquote small color
803 | // $blockquote-small-color:      $gray-light
804 | //* Blockquote font size
805 | // $blockquote-font-size:        ($font-size-base * 1.25)
806 | //* Blockquote border color
807 | // $blockquote-border-color:     $gray-lighter
808 | //* Page header border color
809 | // $page-header-border-color:    $gray-lighter
810 | 
811 | //== Miscellaneous
812 | //
813 | //##
814 | 
815 | //* Horizontal line color.
816 | // $hr-border:                   $gray-lighter
817 | 
818 | //* Horizontal offset for forms and lists.
819 | // $component-offset-horizontal: 180px
820 | 


--------------------------------------------------------------------------------
/content/assets/css/styles.scss:
--------------------------------------------------------------------------------
  1 | // customize bootstrap variables here:
  2 | @import "fonts";
  3 | @import "variables";
  4 | @import "bootstrap";
  5 | @import "search";
  6 | 
  7 | $max-width: $container-lg;
  8 | 
  9 | /* main layout */
 10 | html {
 11 |   width: 100%;
 12 |   overflow: hidden;
 13 |   overflow-y: scroll;
 14 |   
 15 |   /* poor support - but for the future! */
 16 |   hyphens: auto;
 17 |   -webkit-hyphens: auto;
 18 |   -moz-hyphens: auto;
 19 |   -ms-hyphens: auto;
 20 | }
 21 | 
 22 | body {
 23 |   padding-top: $navbar-height;
 24 |   width: 100%;
 25 |   overflow: hidden;
 26 |   overflow-y: initial;
 27 | }
 28 | 
 29 | .top-space {
 30 |   padding-top: 40px;
 31 | }
 32 | 
 33 | h1 {
 34 |   color: $gray-dark;
 35 |   margin-top: 60px;
 36 |   line-height: 0.9em;
 37 | }
 38 | 
 39 | h1 + h2 {
 40 |   margin-top: -0.2em;
 41 | }
 42 | 
 43 | h2 {
 44 |   margin-top: 1.2em;
 45 |   .date {
 46 |     margin-right: 0.2em;
 47 |     color: $brand-primary;
 48 |     font-size: 16px;
 49 |   }
 50 | }
 51 | 
 52 | p {
 53 |   margin-bottom: 0.5em;
 54 |   .fa {
 55 |     display: inline;
 56 |     color: $gray-dark;
 57 |     font-size: 1.1em;
 58 |   }
 59 | }
 60 | 
 61 | i {
 62 |   font-style: normal;
 63 |   font-family: FontAwesome;
 64 | }
 65 | 
 66 | .container, .container-fluid {
 67 |   max-width: $max-width;
 68 | }
 69 | 
 70 | .label {
 71 |   display: inline-block;
 72 |   border-radius: $border-radius-base;
 73 |   padding-top: 0.3em;
 74 |   padding-bottom: 0.1em;
 75 |   font-size: 14px;
 76 |   font-weight: normal;
 77 |   margin-right: 2px;
 78 |   margin-bottom: $padding-small-vertical;
 79 | }
 80 | 
 81 | /* navigation bar */
 82 | .navbar {
 83 |   border: none;
 84 |   
 85 |   .navbar-brand {
 86 |     font-size: 24px;
 87 |     padding: 12px 15px;
 88 |   }
 89 | 
 90 |   .btn.btn-default {
 91 |     padding: 0.2em;
 92 |     height: 1.8em;
 93 |     max-width: 2em;
 94 |     &:hover, &:focus, &:active {
 95 |       color: $brand-primary;
 96 |       background-color: #fff;
 97 |       border-color: #fff;
 98 |     }
 99 |   }
100 |   
101 |   .navbar-form {
102 |     margin-top: 0.8em;
103 |     margin-bottom: 0.8em;
104 |   }
105 |   
106 |   input {
107 |     height: 1.8em;
108 |     padding-top: 6px;
109 |   }
110 |   
111 |   .fa {
112 |     min-width: 20px;
113 |     font-size: 1.3em;
114 |   }
115 | }
116 | 
117 | /* breadcrumb */
118 | #breadcrumb {
119 |   background-color: $gray;
120 |   font-size: 16px;
121 |   ol {
122 |     max-width: $max-width;
123 |     padding: $padding-small-vertical $padding-large-horizontal;
124 |     margin-bottom: 0;
125 |     li + li:before {
126 |       font-family: FontAwesome;
127 |       font-size: 9px;
128 |     }
129 |   }
130 | }
131 | 
132 | /* browse-by-buttons at homescreen */
133 | .browse-button-bar {
134 |   text-align: center;
135 |   margin-top: $padding-large-vertical;
136 |   margin-bottom: $padding-large-vertical;
137 |   .btn-lg {
138 |     margin: $padding-small-vertical $padding-small-horizontal;
139 |   }
140 |   .fa {
141 |     font-size: 1.3em;
142 |   }
143 | }
144 | 
145 | /* news */
146 | h1 + .news-item {
147 |   margin-top: -0.5em;
148 | }
149 | 
150 | /* recording detail site */
151 | .nav.nav-tabs.nav-justified {
152 |   margin-top: 16px;
153 |   font-weight: bold;
154 |   font-size: 24px;
155 |   background-color: $gray;
156 |   
157 |   & > li {
158 |     a {
159 |       padding: $padding-large-vertical 0 0 0;
160 |       margin-bottom: 0;
161 |       border: none;
162 |       &:hover, &:focus, &:active {
163 |         background-color: #fff;
164 |       }
165 |       &:hover, &:focus, &:active {
166 |         border: none;
167 |       }
168 |     }
169 |     &.active > a {
170 |       color: white;
171 |       background-color: $gray-dark;
172 |     }
173 |   }
174 | }
175 | 
176 | .tab-content {
177 |   background-color: $gray-dark;
178 |   
179 |   .tab-pane {
180 |     display: none;
181 |     &.active {
182 |       display: block;
183 |     }
184 |   }
185 |   
186 |   #video {
187 |     text-align: center;
188 |     .video {
189 |       margin: auto;
190 |     }
191 |     * {
192 |       max-width: 100%;
193 |     }
194 |   }
195 |   
196 |   #audio * {
197 |     max-width: 100%;
198 |   }
199 |   
200 |   #download {
201 |     padding: $padding-large-horizontal;
202 |     h3 {
203 |       color: $gray-light;
204 |       &:first-child {
205 |         margin-top: 0;
206 |       }
207 |     }
208 |     ul {
209 |       list-style-type: none;
210 |       padding: 0;
211 |       li {
212 |         min-width: 49%;
213 |         display: inline-block;
214 |       }
215 |       a {
216 |         margin: 0 $padding-xs-horizontal;
217 |       }
218 |     }
219 |     .filetype {
220 |       text-transform: uppercase;
221 |       margin-right: $padding-small-horizontal;
222 |       color: #000;
223 |       background-color: #fff;
224 |       min-width: 4em;
225 |     }
226 |     a:hover, a:focus, a:active {
227 |       text-decoration: none;
228 |     }
229 |   }
230 | 
231 |   #embedshare {
232 |     padding: $padding-large-horizontal;
233 |     input {
234 |       border: 1px solid #d87500;
235 |       color: #d87500;
236 |       border-width: 1px;
237 |       background-color: #555;
238 |     }
239 |     h3 {
240 |       color: $gray-light;
241 |       &:first-child {
242 |         margin-top: 0;
243 |       }
244 |     }
245 |     ul {
246 |       list-style-type: none;
247 |       padding: 0;
248 |       li {
249 |         min-width: 49%;
250 |         display: inline-block;
251 |       }
252 |       a {
253 |         margin: 0 $padding-xs-horizontal;
254 |       }
255 |     }
256 |     a:hover, a:focus, a:active {
257 |       text-decoration: none;
258 |     }
259 |     i {
260 |       color: #d87500;
261 |     }
262 |   }
263 | }
264 | 
265 | ul.metadata {
266 |   list-style: none;
267 |   padding: $padding-small-vertical 0;
268 |   text-align: center;
269 |   border-bottom: 1px solid $gray;
270 |   li {
271 |     display: inline-block;
272 |     min-width: 24.5%;
273 |     padding: $padding-small-vertical $padding-small-horizontal;
274 |   }
275 |   .fa {
276 |     margin-right: $padding-xs-horizontal;
277 |   }
278 | }
279 | 
280 | /* footer */
281 | footer {
282 |   padding: 0.7em;
283 |   margin-top: 2em;
284 |   color: $gray-light;
285 |   background-color: $gray-dark;
286 |   text-align: center;
287 | }
288 | 
289 | /* links */
290 | a.inverted {
291 |   color: $gray-lighter;
292 | }
293 | 
294 | /* buttons */
295 | .btn-lg {
296 |   padding-top: 5px;
297 |   padding-bottom: 5px;
298 |   .fa {
299 |     /* nicely positioned icons on large buttons */
300 |     position: relative;
301 |     top: 0.15em;
302 |     margin-right: 0.3em;
303 |   }
304 | }
305 | 
306 | /* promoted videos */
307 | .promoted {
308 |   width: 100%;
309 |   height: 300px;
310 |   overflow: hidden;
311 |   text-align: center;
312 |   background-image: url('/images/promoted_bg.jpg');
313 |   .carousel.slide {
314 |     height: 290px;
315 |     position: relative;
316 |     top: -112px;
317 |   }
318 |   .carousel-inner {
319 |     height: 100%;
320 |   }
321 |   .item:hover {
322 |     text-decoration: none;
323 |   }
324 |   .item img {
325 |     height: 190px;
326 |     display: inline-block;
327 |     margin-top: 12px;
328 |     border: 1px solid $transparent-white;
329 |   }
330 |   .titlebar {
331 |     width: 100%;
332 |     height: 112px;
333 |     background-color: $transparent-white;
334 |     position: relative;
335 |     top: 188px;
336 |   }
337 |   .carousel-caption {
338 |     position: relative;
339 |     top: 0;
340 |     height: 90px;
341 |     overflow: hidden;
342 |     left: initial;
343 |     right: initial;
344 |     padding: 0;
345 |   }
346 |   .title {
347 |     color: white;
348 |     margin: 0.7em;
349 |     margin-bottom: 0;
350 |   }
351 |   .subtitle {
352 |     font-size: 18px;
353 |     color: $brand-primary;
354 |     margin: 0 0.8em;
355 |     text-overflow: ellipsis;
356 |     white-space: nowrap;
357 |     overflow: hidden;
358 |   }
359 | }
360 | 
361 | /* browse folders and conferences */
362 | .thumbnail {
363 |   display: block;
364 |   float: left;
365 |   text-align: center;
366 |   font-size: 16px;
367 |   min-width: 130px;
368 |   margin: 5px;
369 |   height: 135px;
370 |   
371 |   .header {
372 |     text-align: left;
373 |   }
374 |   
375 |   &:hover, &:focus, &:active {
376 |     text-decoration: none;
377 |   }
378 |   
379 |   &.folder {
380 |     background-color: $brand-primary;
381 |     color: white;
382 |       
383 |     .header {
384 |       margin-bottom: $padding-large-vertical;
385 |     }
386 |     
387 |     .fa.fa-folder {
388 |       font-size: 40px;
389 |       padding: 10px 0;
390 |     }
391 |     
392 |     &:hover, &:focus, &:active {
393 |       background-color: $gray-dark;
394 |     }
395 |     
396 |     .caption {
397 |       color: white;
398 |     }
399 |   }
400 |   
401 |   &.conference {
402 |     color: $gray-dark;
403 |     
404 |     img {
405 |       height: 64px;
406 |       margin: $padding-small-vertical auto;
407 |     }
408 |     
409 |     .caption {
410 |       color: white;
411 |       background-color: $gray-dark;
412 |       -webkit-transition: all 0.2s ease-in-out;
413 |       -o-transition: all 0.2s ease-in-out;
414 |       transition: all 0.2s ease-in-out;
415 |     }
416 |     
417 |     &:hover, &:focus, &:active {
418 |       color: $brand-primary;
419 |       .caption {
420 |         background-color: $brand-primary;
421 |       }
422 |     }
423 |   }
424 | }
425 | 
426 | /* events overview */
427 | .event-previews, .event-previews-tags, .event-previews-search {
428 |   .event-preview {
429 |     margin: 16px 0;
430 |     display: block;
431 |     clear: both;
432 |     height: 120px;
433 |     
434 |     .video-thumbnail {
435 |       float: left;
436 |       height: 120px;
437 |       width: 160px;
438 |     }
439 |     
440 |     color: black;
441 |     &:hover, &:focus, &:active {
442 |       text-decoration: none;
443 |       .caption h3, .metadata li {
444 |         color: $link-color;
445 |       }
446 |     }
447 |     
448 |     .metadata {
449 |       text-align: left;
450 |       border: none;
451 |       li {
452 |         padding: $padding-xs-vertical;
453 |         padding-right: $padding-xs-horizontal;
454 |         color: $gray-dark;
455 |         min-width: inherit;
456 |       }
457 |     }
458 |     
459 |     .caption {
460 |       margin-left: 160px;
461 |       padding-left: $padding-large-horizontal;
462 |       h3 {
463 |         margin-top: 0;
464 |         color: black;
465 |       }
466 |     }
467 |   }
468 | }
469 | 
470 | .events-header {
471 |   clear: both;
472 |   img {
473 |     float: left;
474 |     max-height: 40px;
475 |     margin-right: $padding-small-horizontal;
476 |   }
477 |   #sorting {
478 |     margin: $padding-large-vertical 0;
479 |     float: right;
480 |   }
481 | }
482 | 
483 | /* event overview for tags */
484 | .event-previews-tags .event-preview,
485 | .event-previews-search .event-preview {
486 |     height: auto;
487 |     overflow: hidden;
488 |     
489 |     /* search results numbering */
490 |     h3 .number::after {
491 |       content: '.';
492 |     }
493 |     .conference-logo {
494 |       float: left;
495 |       width: 100px;
496 |       height: auto;
497 |     }
498 |     .caption {
499 |       margin-left: 100px;
500 |     }
501 |     
502 |     .metadata {
503 |       margin-bottom: 0;
504 |     }
505 | }
506 | 
507 | 
508 | .search {
509 |   h1 {
510 |     margin-bottom: 10px;
511 |   }
512 |   .statistics {
513 |     margin-top: 15px;
514 |     display: none;
515 |     &.visible {
516 |       display: block;
517 |     }
518 |   }
519 |   .paging {
520 |     display: none;
521 | 
522 |     clear: both;
523 |     font-size: 24px;
524 |     margin: 50px 0 0 80px;
525 | 
526 |     &.visible {
527 |       display: block;
528 |     }
529 | 
530 |     li {
531 |       display: block;
532 |       text-align: center;
533 |       float: left;
534 |       list-style-type: none;
535 |       padding: 0 5px;
536 | 
537 |       a:hover {
538 |         text-decoration: none;
539 |       }
540 | 
541 |       &.next, &.prev {
542 |         display: none;
543 |         &.visible { display: block; }
544 |       }
545 |       &.next { margin-left: 12px; }
546 |       &.prev { margin-right: 12px; }
547 |       &.active {
548 |         background-color: #555;
549 |         border-radius: 5px;
550 |         a, a:hover {
551 |           color: #eee;
552 |         }
553 |       }
554 |     }
555 |   }
556 | 
557 |   /* search results listing */
558 |   ol.event-previews-search {
559 |     list-style-type: none;
560 |     &, >li {
561 |       margin: 0;
562 |       padding: 0;
563 |     }
564 | 
565 |     >li.no-results {
566 |       margin: 30px 0;
567 |     }
568 |   }
569 | }
570 | 
571 | /* Font classes - Tags */
572 | .tag-cloud { margin-top: 1.5em; }
573 | .tag-cloud .xtiny { font-size: 0.9em; text-decoration:none; }
574 | .tag-cloud .tiny { font-size: 1.1em; font-weight:lighter; }
575 | .tag-cloud .normal{ font-size: 1.3em; text-decoration:none; }
576 | .tag-cloud .large { font-size: 1.5em; text-decoration:none; }
577 | .tag-cloud .xlarge { font-size: 1.75em; font-weight:bold; }
578 | 
579 | 
580 | /* and now for medium screens: */
581 | @media all and (min-width: $screen-sm-min) and (max-width: $container-desktop) {
582 |   
583 |   /* events overview */
584 |   .event-previews .event-preview {
585 |     h3 {
586 |       font-size: 17px;
587 |     }
588 |   }
589 |   
590 | }
591 | 
592 | /* and now for small screens: */
593 | @media all and (max-width: $screen-xs-max) {
594 | 
595 |   /* main layout */
596 |   body {
597 |     padding-top: 0;
598 |   }
599 |   
600 |   h1 {
601 |     font-size: 34px;
602 |     margin-top: 30px;
603 |   }
604 |   h2 {
605 |     font-size: 23px;
606 |   }
607 |   
608 |   /* large buttons */
609 |   .btn-lg, .btn-group-lg>.btn {
610 |     font-size: 23px;
611 |   }
612 | 
613 |   /* navigation bar */
614 |   .navbar {
615 |     position: initial;
616 |     & > .container-fluid {
617 |       display: inline-table;
618 |       width: 100%;
619 |     }
620 |     form {
621 |       width: 100%;
622 |     }
623 |     .navbar-form.navbar-right:last-child {
624 |       margin-right: 0;
625 |     }
626 |     .navbar-header, .navbar-form {
627 |       padding: 0;
628 |       margin-top: 0;
629 |       margin-bottom: 0;
630 |       min-width: 95px;
631 |     }
632 |     .input-group {
633 |       margin-bottom: $padding-small-vertical;
634 |     }
635 |     .button-wrapper {
636 |       text-align: right;
637 |       margin-top: $padding-large-vertical;
638 |     }
639 |   }
640 |   
641 |   /* promoted videos */
642 |   .promoted {
643 |     height: 230px;
644 |     .item img {
645 |       height: 120px;
646 |     }
647 |     .titlebar {
648 |       top: 118px;
649 |     }
650 |   }
651 |   
652 |   /* events overview */
653 |   .event-preview {
654 |     /* one column layout */
655 |     width: 100%;
656 |   }
657 |   
658 |   /* tabs */
659 |   .nav.nav-tabs.nav-justified > li {
660 |     a {
661 |       font-size: 20px;
662 |       padding-top: 5px;
663 |     }
664 |     &.active > a {
665 |       background-color: $gray;
666 |     }
667 |   }
668 |   
669 |   /* events overview */
670 |   .event-previews {
671 |     .event-preview {
672 |       height: auto;
673 |       
674 |       .video-thumbnail {
675 |         margin-top: 1.5em;
676 |         height: 90px;
677 |         width: 120px;
678 |       }
679 |       
680 |       .caption {
681 |         margin-left: 120px;
682 |         padding-left: $padding-small-horizontal;
683 |         h3 {
684 |           height: 90px;
685 |           vertical-align: middle;
686 |           display: table-cell;
687 |           margin-top: 0;
688 |           font-size: 17px;
689 |         }
690 |       }
691 |       .metadata {
692 |         position: relative;
693 |         left: -130px;
694 |         padding: 0;
695 |         margin-bottom: 3px;
696 |         white-space: nowrap;
697 |         margin-bottom: $padding-small-vertical;
698 |       }
699 |     }
700 |   }
701 |   
702 |   /* event overview for searches & tags */
703 |   .event-previews-tags .event-preview,
704 |   .event-previews-search .event-preview {
705 |     h3 {
706 |       font-size: 17px;
707 |     }
708 |     .conference-logo {
709 |       width: 60px;
710 |     }
711 |     .caption {
712 |       margin-left: 60px;
713 |     }
714 |   }
715 | }
716 | 
717 | .mejs-overlay-loading { background: none !important; }
718 | 


--------------------------------------------------------------------------------
/content/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/favicon-16x16.png


--------------------------------------------------------------------------------
/content/favicon-196x196.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/favicon-196x196.png


--------------------------------------------------------------------------------
/content/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/favicon-32x32.png


--------------------------------------------------------------------------------
/content/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/favicon-96x96.png


--------------------------------------------------------------------------------
/content/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/content/favicon.ico


--------------------------------------------------------------------------------
/content/index.haml:
--------------------------------------------------------------------------------
 1 | ---
 2 | title: home
 3 | ---
 4 | 
 5 | = render '/partials/promoted'
 6 | 
 7 | %div.container-fluid
 8 |   .row.browse-button-bar
 9 |     %a.btn.btn-primary.btn-lg{role: 'button', href: '/tags'}
10 |       %span.fa.fa-tags
11 |       Browse by tag
12 | 
13 |     %a.btn.btn-primary.btn-lg{role: 'button', href: '/browse'}
14 |       %span.fa.fa-th
15 |       Browse by category
16 | 
17 |   %h1 News
18 | 
19 |   - News.recent(10).each do |news|
20 |     %article.news-item
21 |       %h2
22 |         %span.date= news.date_formatted
23 |         = news.title
24 |       =news.body
25 | 
26 | 


--------------------------------------------------------------------------------
/content/search.haml:
--------------------------------------------------------------------------------
1 | ---
2 | title: Search
3 | ---
4 | 
5 | = render 'partials/search', :title => 'media.ccc.de-Search'


--------------------------------------------------------------------------------
/content/sitemap.haml:
--------------------------------------------------------------------------------
1 | = xml_sitemap
2 | 


--------------------------------------------------------------------------------
/content/tags/index.haml:
--------------------------------------------------------------------------------
1 | ---
2 | title: Browse by tags
3 | ---
4 | 
5 | %div.container-fluid
6 |   %h1 Browse by tags
7 |   .tag-cloud
8 |     - tag_cloud.each do |tag|
9 |       = tag


--------------------------------------------------------------------------------
/images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/.gitkeep


--------------------------------------------------------------------------------
/images/audio_ready_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/audio_ready_icon.png


--------------------------------------------------------------------------------
/images/dvd_ready_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/dvd_ready_icon.png


--------------------------------------------------------------------------------
/images/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/folder.png


--------------------------------------------------------------------------------
/images/hd_ready_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/hd_ready_icon.png


--------------------------------------------------------------------------------
/images/logos/blinkenlights/folder-blinkenlights.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/blinkenlights/folder-blinkenlights.jpg


--------------------------------------------------------------------------------
/images/logos/broadcast/sendezentrum/sendezentrum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/broadcast/sendezentrum/sendezentrum.png


--------------------------------------------------------------------------------
/images/logos/chaosradio/video/chaosradio-logo-transparent-300.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/chaosradio/video/chaosradio-logo-transparent-300.png


--------------------------------------------------------------------------------
/images/logos/conferences/camp1999/camprocket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/camp1999/camprocket.png


--------------------------------------------------------------------------------
/images/logos/conferences/camp2003/folder-camp-2003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/camp2003/folder-camp-2003.png


--------------------------------------------------------------------------------
/images/logos/conferences/camp2007/folder-camp-2007.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/camp2007/folder-camp-2007.jpg


--------------------------------------------------------------------------------
/images/logos/conferences/camp2011/folder-camp-2011.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/camp2011/folder-camp-2011.png


--------------------------------------------------------------------------------
/images/logos/conferences/camp2015/camp15-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/camp2015/camp15-logo.png


--------------------------------------------------------------------------------
/images/logos/conferences/chaoscologne/1c2/1c2_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/chaoscologne/1c2/1c2_logo.png


--------------------------------------------------------------------------------
/images/logos/conferences/eh2014/logo-navbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/eh2014/logo-navbar.png


--------------------------------------------------------------------------------
/images/logos/conferences/eh2015/eh15v4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/eh2015/eh15v4.png


--------------------------------------------------------------------------------
/images/logos/conferences/fiffkon/2014/fiffkon14-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/fiffkon/2014/fiffkon14-logo.png


--------------------------------------------------------------------------------
/images/logos/conferences/froscon/2010/folder-froscon-2010.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/froscon/2010/folder-froscon-2010.png


--------------------------------------------------------------------------------
/images/logos/conferences/froscon/2011/folder-froscon-2010.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/froscon/2011/folder-froscon-2010.png


--------------------------------------------------------------------------------
/images/logos/conferences/froscon/2012/froscon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/froscon/2012/froscon.png


--------------------------------------------------------------------------------
/images/logos/conferences/froscon/2013/folder-froscon-2010.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/froscon/2013/folder-froscon-2010.png


--------------------------------------------------------------------------------
/images/logos/conferences/froscon/2014/folder-froscon-2010.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/froscon/2014/folder-froscon-2010.png


--------------------------------------------------------------------------------
/images/logos/conferences/froscon/2015/froscon2015.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/froscon/2015/froscon2015.png


--------------------------------------------------------------------------------
/images/logos/conferences/har2009/folder-har-2009.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/har2009/folder-har-2009.png


--------------------------------------------------------------------------------
/images/logos/conferences/mrmcd/mrmcd0x8/folder-mrmcd-2009.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/mrmcd/mrmcd0x8/folder-mrmcd-2009.jpg


--------------------------------------------------------------------------------
/images/logos/conferences/mrmcd/mrmcd101b/folder-mrmcd-2006.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/mrmcd/mrmcd101b/folder-mrmcd-2006.png


--------------------------------------------------------------------------------
/images/logos/conferences/mrmcd/mrmcd111b/folder-mrmcd-2008.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/mrmcd/mrmcd111b/folder-mrmcd-2008.jpg


--------------------------------------------------------------------------------
/images/logos/conferences/mrmcd/mrmcd13/mrmcd2013-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/mrmcd/mrmcd13/mrmcd2013-logo.png


--------------------------------------------------------------------------------
/images/logos/conferences/mrmcd/mrmcd14/mrmcd_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/mrmcd/mrmcd14/mrmcd_14.png


--------------------------------------------------------------------------------
/images/logos/conferences/mrmcd/mrmcd15/mrmcd_15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/mrmcd/mrmcd15/mrmcd_15.png


--------------------------------------------------------------------------------
/images/logos/conferences/sigint09/folder-sigint-2009.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/sigint09/folder-sigint-2009.png


--------------------------------------------------------------------------------
/images/logos/conferences/sigint10/folder-sigint-2010.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/sigint10/folder-sigint-2010.png


--------------------------------------------------------------------------------
/images/logos/conferences/sigint12/folder-sigint-2012.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/sigint12/folder-sigint-2012.jpg


--------------------------------------------------------------------------------
/images/logos/conferences/sigint13/folder-sigint-2013.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/conferences/sigint13/folder-sigint-2013.png


--------------------------------------------------------------------------------
/images/logos/congress/2000/realmedia/folder-17c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2000/realmedia/folder-17c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2001/folder-18c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2001/folder-18c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2002/folder-19c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2002/folder-19c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2003/folder-20c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2003/folder-20c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2004/folder-21c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2004/folder-21c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2005/folder-22c3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2005/folder-22c3.gif


--------------------------------------------------------------------------------
/images/logos/congress/2006/folder-23c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2006/folder-23c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2007/folder-24c3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2007/folder-24c3.jpg


--------------------------------------------------------------------------------
/images/logos/congress/2008/folder-25c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2008/folder-25c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2009/folder-26c3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2009/folder-26c3.jpg


--------------------------------------------------------------------------------
/images/logos/congress/2010/folder-27c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2010/folder-27c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2011/folder-28c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2011/folder-28c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2012/folder-29c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2012/folder-29c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2013/folder-30c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2013/folder-30c3.png


--------------------------------------------------------------------------------
/images/logos/congress/2014/folder-2014.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/congress/2014/folder-2014.png


--------------------------------------------------------------------------------
/images/logos/events/Panoptische_Prinzip/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/Panoptische_Prinzip/logo.jpg


--------------------------------------------------------------------------------
/images/logos/events/cryptocon/2015/cc15_logo_transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/cryptocon/2015/cc15_logo_transparent.png


--------------------------------------------------------------------------------
/images/logos/events/datenspuren/2014/datenspuren2014-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/datenspuren/2014/datenspuren2014-logo.png


--------------------------------------------------------------------------------
/images/logos/events/datenspuren/2015/ds2015.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/datenspuren/2015/ds2015.png


--------------------------------------------------------------------------------
/images/logos/events/gpn/gpn14/80px-Gpn14_logo_navi.jpg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/gpn/gpn14/80px-Gpn14_logo_navi.jpg.png


--------------------------------------------------------------------------------
/images/logos/events/gpn/gpn15/gpn15_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/gpn/gpn15/gpn15_logo.png


--------------------------------------------------------------------------------
/images/logos/events/gpn10/95px-GPN10-TShirt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/gpn10/95px-GPN10-TShirt.png


--------------------------------------------------------------------------------
/images/logos/events/hackover/2013/hackover-2013.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/hackover/2013/hackover-2013.png


--------------------------------------------------------------------------------
/images/logos/events/hackover/2014/hackover-2014.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/hackover/2014/hackover-2014.png


--------------------------------------------------------------------------------
/images/logos/events/hackover/hackover-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/hackover/hackover-logo.png


--------------------------------------------------------------------------------
/images/logos/events/netzpolitik/10np/10np.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/netzpolitik/10np/10np.png


--------------------------------------------------------------------------------
/images/logos/events/netzpolitik/11np/11np.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/netzpolitik/11np/11np.png


--------------------------------------------------------------------------------
/images/logos/events/vcfb/2014/vcfb-logo-quer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/vcfb/2014/vcfb-logo-quer.png


--------------------------------------------------------------------------------
/images/logos/events/vcfb/2014/vcfb2015-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/vcfb/2014/vcfb2015-logo.png


--------------------------------------------------------------------------------
/images/logos/events/wauland/whs_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/wauland/whs_logo.png


--------------------------------------------------------------------------------
/images/logos/events/wie_werden_kriege_gemacht-koeln_2015/unknown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/events/wie_werden_kriege_gemacht-koeln_2015/unknown.png


--------------------------------------------------------------------------------
/images/logos/regional/berlin/datengarten/datengarten.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/regional/berlin/datengarten/datengarten.png


--------------------------------------------------------------------------------
/images/logos/regional/c4/openchaos/c4-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/regional/c4/openchaos/c4-logo.jpg


--------------------------------------------------------------------------------
/images/logos/regional/cccac/vortraege/cccac_logo_bw_kleiner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/regional/cccac/vortraege/cccac_logo_bw_kleiner.png


--------------------------------------------------------------------------------
/images/logos/regional/cccac/vortraege/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/regional/cccac/vortraege/logo.png


--------------------------------------------------------------------------------
/images/logos/unknown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/logos/unknown.png


--------------------------------------------------------------------------------
/images/miro-banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/miro-banner.png


--------------------------------------------------------------------------------
/images/promoted_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/promoted_bg.jpg


--------------------------------------------------------------------------------
/images/rss_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/rss_logo.png


--------------------------------------------------------------------------------
/images/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/spinner.gif


--------------------------------------------------------------------------------
/images/tv-rausch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/tv-rausch.gif


--------------------------------------------------------------------------------
/images/tv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/images/tv.png


--------------------------------------------------------------------------------
/layouts/browse-download-page.haml:
--------------------------------------------------------------------------------
 1 | !!! 5
 2 | %html{lang: 'en'}
 3 |   %head
 4 |     = render '/partials/header'
 5 |     %title
 6 |       C3TV -
 7 |       = h @item[:title]
 8 |     %link{href: '/assets/css/mediaelementplayer.min.css', type: 'text/css', rel: 'stylesheet'}
 9 |   %body
10 |     = render '/partials/navbar'
11 | 
12 |     %div.container-fluid
13 | 
14 |       %h1
15 |         =  h @item[:event].title
16 |       - if @item[:event].subtitle
17 |         %h2
18 |           = h @item[:event].subtitle
19 |       
20 |       %ul.nav.nav-tabs.nav-justified{role: 'tablist'}
21 |         %li
22 |           %a{href: @item[:event].url+'#video', role: 'tab'} Video
23 |         %li 
24 |           %a{href: @item[:event].url+'#audio', role: 'tab'} Audio
25 |         %li.active
26 |           %a{href: '#download', role: 'tab'} Download
27 |           
28 |       .tab-content
29 |         #download.tab-pane.active{style: 'display: block'}
30 |           = render '/partials/download'
31 | 
32 |     = render '/partials/footer'
33 | 


--------------------------------------------------------------------------------
/layouts/browse-index.haml:
--------------------------------------------------------------------------------
 1 | !!! 5
 2 | %html{lang: 'en'}
 3 |   %head
 4 |     = render '/partials/header'
 5 |     %title
 6 |       C3TV -
 7 |       = h @item[:title]
 8 |   %body
 9 |     = render '/partials/navbar'
10 | 
11 |     .container-fluid
12 |       %h1 Browse by category
13 | 
14 |       - if @item[:folders].present?
15 |         - @item[:folders].each do |folder|
16 |           - if folder.conference
17 |             %a.thumbnail.conference{href: h(folder.url)}
18 |               .header
19 |                 %span.fa.fa-video-camera
20 |                 = Event.recorded_at(folder.conference).to_a.count
21 |               %img{src: folder.conference.logo_url, alt: 'conference logo'}
22 |               .caption
23 |                 = folder.conference.title
24 |           - else
25 |             %a.thumbnail.folder{href: h(folder.url)}
26 |               .header
27 |                 %span.fa.fa-th
28 |               .fa.fa-folder
29 |               .caption
30 |                 = folder.name
31 | 
32 |       = yield
33 | 
34 |     = render '/partials/footer'
35 | 


--------------------------------------------------------------------------------
/layouts/browse-oembed-page.haml:
--------------------------------------------------------------------------------
 1 | !!! 5
 2 | %html{lang: 'en'}
 3 |   %head
 4 |     %title
 5 |       C3TV -
 6 |       = h @item[:title]
 7 |     %link{href: '/assets/css/mediaelementplayer.min.css', type: 'text/css', rel: 'stylesheet'}
 8 |   %body
 9 |     %div.container-fluid
10 |       = render '/partials/videoplayer'
11 | 
12 |     %script(src='/assets/js/jquery.min.js')
13 |     %script(src='/assets/js/bootstrap.min.js')
14 |     %script(src='/assets/js/mediaelement-and-player.min.js')
15 | 
16 |     = render '/partials/videoplayer_js'
17 | 


--------------------------------------------------------------------------------
/layouts/browse-show-folder.haml:
--------------------------------------------------------------------------------
 1 | !!! 5
 2 | %html{lang: 'en'}
 3 |   %head
 4 |     = render '/partials/header'
 5 |     %title
 6 |       C3TV -
 7 |       = h @item[:title]
 8 |     = render '/partials/folder-feeds'
 9 |   %body
10 |     = render '/partials/navbar'
11 | 
12 |     .container-fluid
13 | 
14 |       .events-header
15 |         %img{src: @item[:conference].logo_url, alt: 'conference logo'}
16 | 
17 |         %h1= @item[:conference].acronym.gsub(/[\-_]/,' ')
18 |         - if @item[:conference].title and not item[:conference].acronym == @item[:conference].title
19 |           %h2= h @item[:conference].title
20 | 
21 |         #sorting.btn-group.btn-group-sm.btn-group-justified
22 |           - %w{name duration date}.each do |sorting|
23 |             - if @item[:sorting] == sorting
24 |               %a.btn.btn-primary.active{ href: "/browse/#{@item[:conference].webgen_location}/#{sorting}/" }= sorting
25 |             - else
26 |               %a.btn.btn-primary{ href: "/browse/#{@item[:conference].webgen_location}/#{sorting}/" }= sorting
27 | 
28 |       - if @item[:events].present?
29 |         .event-previews
30 |           -# Build event overview
31 |           - @item[:events].each do |event|
32 |             - recordings = event.recordings.downloaded
33 |             %a.event-preview{href: h(event.url)}
34 |               %img.video-thumbnail{src: h(event.thumb_url), alt: h(event.title)}
35 |               .caption
36 |                 %ul.metadata
37 |                   %li
38 |                     %span.fa.fa-clock-o
39 |                     = recording_length(recordings)
40 |                   %li
41 |                     %span.fa.fa-calendar-o
42 |                     = date(event)
43 |                   %li.persons
44 |                     %span.fa{class: event.persons_icon}
45 |                     = event.persons_text
46 |                 %h3= h event.title
47 | 
48 |       = yield
49 | 
50 |     = render '/partials/footer'
51 | 


--------------------------------------------------------------------------------
/layouts/browse-show-page.haml:
--------------------------------------------------------------------------------
  1 | !!! 5
  2 | %html{lang: 'en'}
  3 |   %head
  4 |     = render '/partials/header'
  5 |     %title
  6 |       C3TV -
  7 |       = h @item[:title]
  8 |     = render '/partials/folder-feeds'
  9 |     %link{href: '/assets/css/mediaelementplayer.min.css', type: 'text/css', rel: 'stylesheet'}
 10 |     != ""
 11 |   %body
 12 |     %script(src='/assets/js/jquery.min.js')
 13 |     = render '/partials/navbar'
 14 | 
 15 |     %div.container-fluid
 16 |       %h1
 17 |         =  h @item[:event].title
 18 |       - if @item[:event].subtitle
 19 |         %h2
 20 |           = h @item[:event].subtitle
 21 | 
 22 |       %p.persons
 23 |         %span.fa{class: @item[:event].persons_icon}
 24 |           - @item[:event].persons.to_enum.with_index(1).each do |speaker, index|
 25 |             - if (@item[:event].persons.count - 1) == index
 26 |               %a{href: '/search/?q=' + h(speaker)}= speaker
 27 |               and
 28 |             - elsif @item[:event].persons.count == index
 29 |               %a{href: '/search/?q=' + h(speaker)}= speaker
 30 |             - else
 31 |               = succeed "," do
 32 |                 %a{href: '/search/?q=' + h(speaker)}= speaker
 33 | 
 34 | 
 35 |       %ul.nav.nav-tabs.nav-justified{role: 'tablist', 'data-tabs' => 'tabs'}
 36 |         - if @item[:video_recordings].present?
 37 |           %li
 38 |             %a{href: '#video', role: 'tab', 'data-toggle' => 'tab'} Video
 39 |         - if @item[:audio_recordings].present?
 40 |           %li
 41 |             %a{href: '#audio', role: 'tab', 'data-toggle' => 'tab'} Audio
 42 |         %li
 43 |           %a{href: @item[:event].download_url, 'data-target' => '#download', role: 'tab', 'data-toggle' => 'tab'} Download
 44 | 
 45 |         %li
 46 |           %a{href: '#embedshare', role: 'tab', 'data-toggle' => 'tab'} Share
 47 | 
 48 |       .tab-content
 49 |         - if @item[:video_recordings].present?
 50 |           #video.tab-pane.active
 51 |             = render '/partials/videoplayer'
 52 | 
 53 |         - if @item[:audio_recordings].present?
 54 |           #audio.tab-pane
 55 |             %audio.audio{controls: 'controls'}
 56 |               - @item[:audio_recordings].each do |recording|
 57 |                 %source{type: recording.display_mime_type, src: h(recording.url)}
 58 | 
 59 |         #download.tab-pane
 60 |           = render '/partials/download'
 61 | 
 62 |         #embedshare.tab-pane
 63 |           = render '/partials/embedshare'
 64 | 
 65 |       %ul.metadata
 66 |         %li
 67 |           %span.fa.fa-clock-o
 68 |           = recording_length(@item[:event].recordings.downloaded)
 69 |         %li
 70 |           %span.fa.fa-calendar-o
 71 |           = date(@item[:event])
 72 |         %li
 73 |           %span.fa.fa-eye
 74 |           = @item[:event].view_count
 75 |         %li
 76 |           %span.fa.fa-external-link
 77 |           %a{href: @item[:event].link}
 78 |             = parse_url_host(@item[:event])
 79 | 
 80 |       - if @item[:event].description.present?
 81 |         %h3 About
 82 |         %p.description
 83 |           = @item[:event].description
 84 | 
 85 |       - if @item[:event].tags.present?
 86 |         %h3 Tags
 87 |         - @item[:event].tags.each do |tag|
 88 |           = link_for(tag)
 89 | 
 90 | 
 91 | 
 92 |     = render '/partials/footer'
 93 | 
 94 |     %script(src='/assets/js/bootstrap.min.js')
 95 |     %script(src='/assets/js/mediaelement-and-player.min.js')
 96 | 
 97 |     = render '/partials/videoplayer_js'
 98 | 
 99 |     :javascript
100 | 
101 |       $('audio').mediaelementplayer();
102 | 
103 |       // activate tab via hash and default to video
104 |       function setTabToHash() {
105 |         var hash = window.location.hash.split('&')[0]; // split video-stamp of the hash
106 |         var activeTab = $('.nav-tabs a[href=' + hash + '], .nav-tabs a[data-target=' + hash + ']')
107 |           .tab('show');
108 | 
109 |         if (activeTab.length === 0) {
110 |           var hash = '#video';
111 |           if(window.history && window.history.replaceState) {
112 |             // set new hash without adding an entry into the browser history
113 |             window.history.replaceState(null, "", hash);
114 |           }
115 |           else {
116 |             // classic fallback
117 |             window.location.hash = hash;
118 |           }
119 |         }
120 |       }
121 |       setTabToHash();
122 | 
123 |       // change hash on tab change
124 |       $('.nav-tabs a').on('shown.bs.tab', function (e) {
125 |         window.location.hash = e.target.hash;
126 |       });
127 | 
128 |       // adjust tabs when hash changes
129 |       window.onhashchange = setTabToHash;
130 | 


--------------------------------------------------------------------------------
/layouts/browse-show-tags.haml:
--------------------------------------------------------------------------------
 1 | !!! 5
 2 | %html{lang: 'en'}
 3 |   %head
 4 |     = render '/partials/header'
 5 |     %title
 6 |       C3TV -
 7 |       = h @item[:title]
 8 |   %body
 9 |     = render '/partials/navbar'
10 |     
11 |     %div.container-fluid
12 |       %h1 Events for tag "#{@item[:title]}"
13 |       
14 |       .event-previews-tags
15 |         - if @item[:events].present?
16 |           - @item[:events].each do |event|
17 |             - recordings = event.recordings.downloaded
18 |             .event-preview
19 |               %a{href: h(event.url)}
20 |                 %img.conference-logo{src: h(event.conference.logo_url), alt: h(event.conference.title)}
21 |               .caption
22 |                 %ul.metadata
23 |                   %li
24 |                     %span.fa.fa-clock-o
25 |                     = recording_length(recordings)
26 |                   %li
27 |                     %span.fa.fa-calendar-o
28 |                     = date(event)
29 |                   %li.persons
30 |                     %span.fa{class: event.persons_icon}
31 |                     = event.linked_persons_text
32 |                 %h3
33 |                   %a{href: h(event.url)}
34 |                     = h event.title
35 | 
36 |       = yield
37 | 
38 |     = render '/partials/footer'
39 | 


--------------------------------------------------------------------------------
/layouts/default.haml:
--------------------------------------------------------------------------------
 1 | !!! 5
 2 | %html{lang: 'en'}
 3 |   %head
 4 |     = render '/partials/header'
 5 |     %title
 6 |       C3TV -
 7 |       = @item[:title]
 8 |     %script(src="/assets/js/jquery.min.js")
 9 |     %script(src="/assets/js/bootstrap.min.js")
10 |     %script(src="/assets/js/purl.min.js")
11 |     %script(src="/assets/js/search.js")
12 |   %body
13 |     = render '/partials/navbar'
14 |     = yield
15 | 
16 |     = render '/partials/footer'
17 | 
18 | 


--------------------------------------------------------------------------------
/layouts/partials/download.haml:
--------------------------------------------------------------------------------
 1 | - if @item[:video_recordings].present?
 2 |   %h3 Video
 3 |   %ul
 4 |     - video_download_sources(@item[:video_recordings]).each do |recording|
 5 |       %li
 6 |         %span.label.filetype= recording.filetype
 7 |         %a{href: recording.url, download: true}
 8 |           %span.fa.fa-download
 9 |           http download
10 |         %a{href: recording.torrent_url, download: true}
11 |           %span.fa.fa-download
12 |           torrent
13 | 
14 | - if @item[:audio_recordings].present?
15 |   %h3 Audio
16 |   %ul
17 |     - @item[:audio_recordings].each do |recording|
18 |       %li
19 |         .label.filetype= recording.filetype
20 |         %a{href: recording.url, download: true}
21 |           %span.fa.fa-download
22 |           http download
23 |         %a{href: recording.torrent_url, download: true}
24 |           %span.fa.fa-download
25 |           torrent
26 | 
27 | %h3 Parent directory
28 | %a{href: @item[:conference].recordings_url}
29 |   %span.fa.fa-folder-open
30 |   = @item[:conference].recordings_path
31 | 


--------------------------------------------------------------------------------
/layouts/partials/embedshare.haml:
--------------------------------------------------------------------------------
 1 | %h3 Embed into your website
 2 | %input{:type => "text", :size=> "85", :readonly => true, :id => "txtShareFrame",
 3 |        :value => ""}
 4 | %h3 Share with others
 5 | %ul
 6 |   %li
 7 |     %a{:id => "btnTweet", :href => twitter_url(@item[:title], page_url(@item)) }
 8 |       %i{:class => "fa-twitter"}
 9 |       via Twitter
10 |   %li
11 |     %a{:id => "btnFacebook",
12 |        :href => facebook_url(@item[:title], page_url(@item)) }
13 |       %i{:class => "fa-facebook-square"}
14 |       via Facebook
15 |   %li
16 |     %a{:id => "btnGPlus", :href => googleplus_url(@item[:title], page_url(@item)) }
17 |       %i{:class => "fa-google-plus"}
18 |       via Google+
19 |   %li
20 |     %a{:id => "btnAppNet", :href => appnet_url(@item[:title], page_url(@item)) }
21 |       %i{:class => "fa-adn"}
22 |       via App.net
23 |   %li
24 |     %a{:id => "btnMail", :href => mail_url(@item[:title], page_url(@item)) }
25 |       %i{:class => "fa-envelope"}
26 |       by Mail
27 | :javascript
28 |   $(function() {
29 |     $('#btnTweet, #btnFacebook, #btnGPlus, #btnAppNet').on('click', function (e) {
30 |       window.open(this.href, 'share it', 'width=550,height=420,resizable=yes');
31 |       e.preventDefault();
32 |     });
33 |     $("#txtShareFrame").on('focus', function() {
34 |       $(this).select();
35 |     });
36 |   });
37 | 
38 | 


--------------------------------------------------------------------------------
/layouts/partials/folder-feeds.haml:
--------------------------------------------------------------------------------
1 | - path = '../' if @item.identifier.match %r[(?:date|duration|name)/$]
2 | - @item[:conference].mime_types do |mime_type, mime_type_name|
3 |   %link{rel: "alternate", type: "application/rss+xml", title: "Podcast feed #{MimeType.humanized_mime_type(mime_type)} for this folder", href: "#{path}podcast-#{mime_type_name}.xml"}
4 |   %link{rel: "alternate", type: "application/rss+xml", title: "Torrent feed #{MimeType.humanized_mime_type(mime_type)} for this folder", href: "#{path}broadcatching-#{mime_type_name}.rss"}
5 | 


--------------------------------------------------------------------------------
/layouts/partials/footer.haml:
--------------------------------------------------------------------------------
1 | %footer
2 |   by 
3 |   %a.inverted{href: '//ccc.de'} Chaos Computer Club e.V
4 | 


--------------------------------------------------------------------------------
/layouts/partials/header.haml:
--------------------------------------------------------------------------------
 1 | %meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'}
 2 | %meta{'http-equiv' => 'Content-Type', content: 'text/html; charset=UTF-8'}
 3 | %meta{name: "robots", content: "index,follow"}
 4 | %meta{name: 'author', content: Settings.header['author']}
 5 | %meta{name: 'description', content: Settings.header['description']}
 6 | %meta{name: "keywords", content: keywords}
 7 | %meta{name: "google-site-verification", content: Settings.header['google']}
 8 | %meta{name: 'viewport', content: 'width=device-width, initial-scale=1.0'}
 9 | 
10 | %link{rel: "apple-touch-icon", sizes: "57x57", href: "/apple-touch-icon-57x57.png"}
11 | %link{rel: "apple-touch-icon", sizes: "72x72", href: "/apple-touch-icon-72x72.png"}
12 | %link{rel: "apple-touch-icon", sizes: "60x60", href: "/apple-touch-icon-60x60.png"}
13 | %link{rel: "apple-touch-icon", sizes: "76x76", href: "/apple-touch-icon-76x76.png"}
14 | %link{rel: "icon", type: "image/png", href: "/favicon-96x96.png", sizes: "96x96"}
15 | %link{rel: "icon", type: "image/png", href: "/favicon-16x16.png", sizes: "16x16"}
16 | %link{rel: "icon", type: "image/png", href: "/favicon-32x32.png", sizes: "32x32"}
17 | 
18 | %link{href: '/assets/css/font-awesome.min.css', rel: 'stylesheet'}
19 | %link{href: '/assets/css/styles.css', rel: 'stylesheet'}
20 | %link{rel: 'alternate', type: 'application/atom+xml', title: 'C3TV - News', href: '/news.atom'}
21 | %link{rel: "alternate", type: "application/rss+xml", title: "C3TV - RSS, last 100", href: "/updates.rdf"}
22 | %link{rel: "alternate", type: "application/rss+xml", title: "C3TV - Podcast feed of the last two years", href: "/podcast.xml"}
23 | %link{rel: "alternate", type: "application/rss+xml", title: "C3TV - Podcast archive feed", href: "/podcast-archive.xml"}
24 | 


--------------------------------------------------------------------------------
/layouts/partials/navbar.haml:
--------------------------------------------------------------------------------
 1 | %div.navbar.navbar-default.navbar-fixed-top(role="navigation")
 2 |   %div.container-fluid
 3 |     %div.navbar-header
 4 |       %a.navbar-brand(href='/index.html')
 5 |         %img{src: '/images/tv.png', alt: 'ccc-tv logo, a tv displaying a play icon'}
 6 |         ccc-tv
 7 | 
 8 |     .nav.navbar-form.navbar-right.button-wrapper
 9 |       - if @item[:conference] and Recording.recorded_at(@item[:conference]).count > 0
10 |         - path = '../' if @item.identifier.match %r[(?:date|duration|name)/$]
11 |         %a.form-control.btn.btn-default{href: "#{path}podcast-#{@item[:conference].preferred_mime_type}.xml"}
12 |           %span.fa.fa-rss
13 |         %a.form-control.btn.btn-default{href: "#{path}broadcatching-#{@item[:conference].preferred_mime_type}.rss"}
14 |           %span.fa.fa-magnet
15 |       - else
16 |         %a.form-control.btn.btn-default{href: '/podcast.xml'}
17 |           %span.fa.fa-rss
18 | 
19 |           %span.fa.fa-magnet
20 |       %a.form-control.btn.btn-default{href: '/about.html'}
21 |         %span.fa.fa-info
22 |     %form.navbar-form.navbar-right{role: 'search', action: '/search/', method: 'get', id: 'media-search'}
23 |       %div.form-group.input-group
24 |         %input.form-control{type: 'search', size: '17', name: 'q', placeholder: 'Search…'}
25 |         %span.input-group-btn
26 |           %button.btn.btn-default{type: 'submit'}
27 |             %span.fa.fa-search
28 | 
29 | - event_page_or_folder(@item) do |trail|
30 |   #breadcrumb
31 |     %ol.container-fluid.breadcrumb
32 |       - trail[1..-2].each_with_index do |item, i|
33 |         %li
34 |           %a.inverted{href: item.identifier}
35 |             = item.identifier.sub(trail[i].identifier, '').gsub('/','').gsub(/[\-_]/,' ')
36 |       %li.active
37 |         - if @item[:sorting] == '' || @item[:sorting] == nil
38 |           - if trail[-1][:event].present?
39 |             = trail[-1][:title]
40 |           - else
41 |             = trail[-1].identifier.sub(trail[-2].identifier, '').gsub('/','')
42 |         - else
43 |           = "sorted by #{trail[-1].identifier.sub(trail[-2].identifier, '').gsub('/','')}"
44 | 


--------------------------------------------------------------------------------
/layouts/partials/promoted.haml:
--------------------------------------------------------------------------------
 1 | %div.promoted
 2 |   .titlebar
 3 |   .carousel.slide{'data-ride' => 'carousel'}
 4 |     .carousel-inner
 5 |       - Event.promoted(10).each_with_index do |event, i|
 6 |         %a.item{href: h(event.url), 'class' => (i == 0 and 'active')}
 7 |           %img{src: h(event.thumb_url), alt: event.title, title: event.title}
 8 |           .carousel-caption
 9 |             %h2.title= event.title
10 |             - if event.subtitle.present?
11 |               %h3.subtitle= event.subtitle
12 | 


--------------------------------------------------------------------------------
/layouts/partials/search.haml:
--------------------------------------------------------------------------------
 1 | .search.container-fluid{"data-titletpl" => '"#" - Search - media.ccc.de'}
 2 |   %form.initial{role: 'search'}
 3 |     %h1{"data-resulttpl" => 'Search for "#"'}
 4 |       = @title
 5 | 
 6 |     %input.form-control.text{type: 'search', size: '17', name: 'q', placeholder: 'Search…'}
 7 |     %span.input-group-btn
 8 |       %button.btn.btn-default.submit{type: 'submit'}
 9 |         %span.fa.fa-search
10 | 
11 |   %section.results.initial
12 |     .statistics
13 |       Results
14 |       %span.start #
15 | 
16 |       to
17 |       %span.end #
18 | 
19 |       of
20 |       %span.total #
21 | 
22 |       Results (in
23 |       %span.runtime #
24 |       ms)
25 | 
26 |     %ol.event-previews-search
27 |       %li.no-results
28 |         Unfortunately your search did not return any results. Maybe you can find what you're looking for by
29 |         %a{href: '/tags/'} browsing the tags
30 |         or
31 |         %a{href: '/browse/'} by category.
32 |       %li.template
33 |         .event-preview
34 |           %a.conference-url{href: '#event.url'}
35 |             %img.conference-logo{src: '#event.conference.logo_url', alt: '#event.conference.title'}
36 |           .caption
37 |             %ul.metadata
38 |               %li.recording_length
39 |                 %span.fa.fa-clock-o
40 |                 %span.t= 'recording_length(event.recordings.downloaded)'
41 |               %li.date
42 |                 %span.fa.fa-calendar-o
43 |                 %span.t= 'date(event)'
44 |               %li.persons
45 |                 %span.persons.fa
46 |                 %span.t= 'event.persons_text'
47 |             %h3
48 |               %a.conference-url{href: '#event.url'}
49 |                 %span.number
50 |                 %span.t= 'event.title'
51 | 
52 |     %ul.paging
53 |       %li.prev
54 |         %a.fa.fa-chevron-left{:href => ""}
55 |       %li.prefix M
56 | 
57 |       %li.page.template
58 |         %a{:href => "#"}
59 |           .letter e
60 |           .number 1
61 | 
62 |       %li.postfix dia.ccc.de
63 |       %li.next
64 |         %a.fa.fa-chevron-right{:href => ""}
65 | 


--------------------------------------------------------------------------------
/layouts/partials/videoplayer.haml:
--------------------------------------------------------------------------------
1 | %video.video{controls: 'controls', poster: h(@item[:event].poster_url), width: aspect_ratio_width, height: aspect_ratio_height}
2 |   - video_tag_sources(@item[:video_recordings]).each do |recording|
3 |     %source{type: recording.display_mime_type, src: h(recording.url)}
4 |   %object{ width: aspect_ratio_width, height: aspect_ratio_height, type: 'application/x-shockwave-flash', data: '/assets/flashmediaelement.swf' }
5 |     %param{ name: 'allowFullScreen', value: 'true' }
6 |     %param{ name: 'flashvars', value: "controls=true&file=#{flash(@item[:video_recordings])}" }
7 | 


--------------------------------------------------------------------------------
/layouts/partials/videoplayer_js.haml:
--------------------------------------------------------------------------------
 1 | :javascript
 2 |   var stamp = window.location.hash.split('&t=')[1];
 3 |   $('video').mediaelementplayer({
 4 |     usePluginFullScreen: true,
 5 | 
 6 |     pluginPath: '/assets/',
 7 |     enableAutosize: true,
 8 |     success: function (mediaElement) {
 9 |       mediaElement.addEventListener('canplay', function () {
10 |         if(stamp) {
11 |           mediaElement.setCurrentTime(stamp);
12 |           stamp = null;
13 |         }
14 |       });
15 |       mediaElement.addEventListener('playing', function () {
16 |         $.post("//api.media.ccc.de/public/recordings/count", {event_id: #{@item[:event].id},src: mediaElement.src});
17 |       }, false);
18 |       mediaElement.addEventListener('pause', function() {
19 |         var hash = '#video&t='+Math.round(mediaElement.currentTime);;
20 |         if(window.history && window.history.replaceState) {
21 |           // set new hash without adding an entry into the browser history
22 |           window.history.replaceState(null, "", hash);
23 |         }
24 |         else {
25 |           // classic fallback
26 |           window.location.hash = hash;
27 |         }
28 |       }, false);
29 |     }
30 |   });
31 | 


--------------------------------------------------------------------------------
/lib/data_source.rb:
--------------------------------------------------------------------------------
 1 | require 'active_record'
 2 | require 'active_support/all'
 3 | 
 4 | class MediaBackendDataSource < Nanoc3::DataSource
 5 | 
 6 |   identifier :media_backend
 7 | 
 8 |   def up
 9 |     ActiveRecord::Base.establish_connection(@site.config[:database])
10 |     @cache = ActiveSupport::Cache.lookup_store(:file_store, 'tmp/cache')
11 |   end
12 | 
13 |   def items
14 |     item_builder = ItemBuilder.new
15 |     build_conference_items(item_builder)
16 |     item_builder.items
17 |   end
18 | 
19 |   private
20 | 
21 |   def build_conference_items(item_builder)
22 |     tag_pages = TagPages.new
23 |     location_pages = LocationPages.new
24 |     feed_builder = FeedBuilder.new(item_builder)
25 | 
26 |     Conference.order("created_at desc").all.each do |conference|
27 |       # event pages
28 |       events = conference.events.select { |event| event.recordings.downloaded.any? }
29 | 
30 |       # conference folders
31 |       item_builder.create_conference_item(conference, events)
32 |       location_pages.add(conference.webgen_location)
33 | 
34 |       events.each do |event|
35 |         date = cached_date(event)
36 |         if ENV['FAST_NANOC']
37 |           item_builder.create_event_item(event) if date.nil? || event.updated_at > date
38 |         else
39 |           item_builder.create_event_item(event)
40 |         end
41 |       end
42 | 
43 |       tag_pages.add(events)
44 |       feed_builder.add(conference, events)
45 |     end
46 | 
47 |     raise "duplicate location in conferences" if location_pages.duplicate?
48 | 
49 |     # build tag pages
50 |     tag_pages.apply(item_builder)
51 | 
52 |     # build connecting folder items
53 |     location_pages.apply(item_builder)
54 | 
55 |     feed_builder.apply
56 |   end
57 | 
58 |   # @return nil if item was just added to the cache, otherwise the cached date
59 |   def cached_date(event)
60 |     key = ['event', event.guid]
61 |     date = @cache.read(key)
62 |     @cache.write(key, event.updated_at)
63 |     date
64 |   end
65 | 
66 | end
67 | 


--------------------------------------------------------------------------------
/lib/data_source/feed_builder.rb:
--------------------------------------------------------------------------------
 1 | class FeedBuilder
 2 | 
 3 |   def initialize(item_builder)
 4 |     @item_builder = item_builder
 5 |     @cache = ActiveSupport::Cache.lookup_store(:file_store, 'tmp/cache')
 6 |   end
 7 | 
 8 |   def add(conference, events)
 9 |     conference.mime_types do |mime_type, mime_type_name|
10 |       name = "podcast-#{mime_type_name}"
11 |       xml = @cache.fetch(cache_key(name, conference, events)) do
12 |         Feeds::PodcastGenerator.generate events: events, query: :by_mime_type, config: {
13 |           mime_type: mime_type,
14 |           title: "#{conference.title} (#{mime_type_name})",
15 |           channel_summary: "This feed contains all events from #{conference.acronym} as #{mime_type_name}"
16 |         }
17 |       end
18 |       @item_builder.create_folder_feed_item(conference, identifier: name, content: xml)
19 |     end
20 | 
21 |     # broadcatching
22 |     conference.mime_types do |mime_type, mime_type_name|
23 |       name = "broadcatching-#{mime_type_name}"
24 |       xml = @cache.fetch(cache_key(name, conference, events)) do
25 |         Feeds::BroadcatchingGenerator.generate events: events, query: :by_mime_type, config: {
26 |           mime_type: mime_type,
27 |           title: "#{conference.title} (#{mime_type_name})",
28 |           channel_summary: "This feed contains all torrents for #{mime_type_name} from #{conference.acronym}"
29 |         }
30 |       end
31 |       @item_builder.create_folder_feed_item(conference, identifier: name, content: xml, extension: 'rss')
32 |     end
33 |   end
34 | 
35 |   def apply
36 |     # rss 1.0 last 100 feed
37 |     events = Event.recent(100)
38 |     xml = @cache.fetch(cache_key(:events100, events)) do
39 |       Feeds::RDFGenerator.generate events: events, config: {
40 |         title: 'last 100 events feed',
41 |         channel_summary: "This feed the most recent 100 events"
42 |       }
43 |     end
44 |     @item_builder.create_feed_item(xml, 'updates.rdf')
45 | 
46 |     # podcast_recent
47 |     events = Event.newer(Time.now.ago(2.years))
48 |     xml = @cache.fetch(cache_key(:events_two_years, events)) do
49 |       Feeds::PodcastGenerator.generate events: events, query: :preferred_recording, config: {
50 |         title: 'recent events feed',
51 |         channel_summary: "This feed contains events from the last two years"
52 |       }
53 |     end
54 |     @item_builder.create_feed_item(xml, 'podcast.xml')
55 | 
56 |     # podcast_archive
57 |     events = Event.older(Time.now.ago(2.years))
58 |     xml = @cache.fetch(cache_key(:events_older, events)) do
59 |       Feeds::PodcastGenerator.generate events: events, query: :preferred_recording, config: {
60 |         title: 'archive feed',
61 |         channel_summary: "This feed contains events older than two years"
62 |       }
63 |     end
64 |     @item_builder.create_feed_item(xml, 'podcast-archive.xml')
65 | 
66 |     # news atom feed
67 |     news = News.all
68 |     atom_feed = @cache.fetch(cache_key(:news, news)) do
69 |       Feeds::NewsFeedGenerator.generate(news, options: {
70 |         author: Settings.feeds['channel_owner'],
71 |         about: 'http://media.ccc.de/',
72 |         title: 'CCC TV - NEWS',
73 |         feed_url: 'http://media.ccc.de/news.atom',
74 |         icon: 'http://media.ccc.de/favicons.ico',
75 |         logo: 'http://media.ccc.de/images/tv.png'
76 |       })
77 |     end
78 |     @item_builder.create_feed_item(atom_feed, 'news.atom')
79 |   end
80 | 
81 |   private
82 | 
83 |   def cache_key(identifier, *models)
84 |     identifier.to_s + '_' + Digest::SHA1.hexdigest([models.flatten.map { |m| m.updated_at.to_i }].join(';'))
85 |   end
86 | 
87 | end
88 | 


--------------------------------------------------------------------------------
/lib/data_source/item_builder.rb:
--------------------------------------------------------------------------------
  1 | class ItemBuilder
  2 | 
  3 |   def initialize
  4 |     @items = []
  5 |   end
  6 |   attr_reader :items
  7 | 
  8 |   def create_conference_item(conference, events)
  9 |     ['', 'name', 'duration', 'date'].each do |sorting|
 10 |       @items << Nanoc3::Item.new(
 11 |         "",
 12 |         {
 13 |           title: conference_title(conference), layout: 'browse-show-folder',
 14 |           conference: conference, events: sorting_events(events, sorting),
 15 |           sorting: sorting
 16 |         },
 17 |         get_path([conference.webgen_location, "#{sorting}"]),
 18 |         binary: false
 19 |       )
 20 |     end
 21 |   end
 22 | 
 23 |   def create_event_item(event)
 24 |     description = ""
 25 |     if event.description.present?
 26 |       description = event.description
 27 |     end
 28 | 
 29 |     @items << Nanoc3::Item.new(
 30 |       description,
 31 |       event_attributes(event).merge(layout: 'browse-show-page'),
 32 |       get_path(event.conference.webgen_location, event.slug),
 33 |       binary: false
 34 |     )
 35 | 
 36 |     @items << Nanoc3::Item.new(
 37 |       description,
 38 |       event_attributes(event).merge(layout: 'browse-download-page'),
 39 |       get_path(event.conference.webgen_location, event.slug)+'download/',
 40 |       binary: false
 41 |     )
 42 | 
 43 |     @items << Nanoc3::Item.new(
 44 |       description,
 45 |       event_attributes(event).merge(layout: 'browse-oembed-page'),
 46 |       get_path(event.conference.webgen_location, event.slug)+'oembed/',
 47 |       binary: false
 48 |     )
 49 |   end
 50 | 
 51 |   def create_browse_item(path, childs)
 52 |     folders = []
 53 |     childs.each { |child|
 54 |       if path == '/'
 55 |         location = child
 56 |       else
 57 |         location = File.join(path, child)
 58 |       end
 59 |       folder = Folder.new(location: location)
 60 |       res = Conference.where(webgen_location: location)
 61 |       folder.conference = res.first unless res.nil? or res.empty?
 62 |       folders << folder
 63 |     }
 64 | 
 65 |     title = path
 66 |     if path == "/"
 67 |       title = "Browse by category"
 68 |     end
 69 | 
 70 |     @items << Nanoc3::Item.new(
 71 |       "",
 72 |       {
 73 |         title: title, layout: 'browse-index',
 74 |         folders: folders
 75 |       },
 76 |       get_path(path),
 77 |       binary: false
 78 |     )
 79 |   end
 80 | 
 81 |   def create_tag_item(tag, events)
 82 |     @items << Nanoc3::Item.new(
 83 |       "",
 84 |       {
 85 |         title: tag, layout: 'browse-show-tags',
 86 |         tag: true,
 87 |         events: events
 88 |       },
 89 |       get_path('tags', tag),
 90 |       binary: false
 91 |     )
 92 |   end
 93 | 
 94 |   def create_feed_item(content, filename)
 95 |     identifier, extension = filename.split('.')
 96 |     @items << Nanoc3::Item.new(
 97 |       content,
 98 |       {
 99 |         extension: extension
100 |       },
101 |       "/#{identifier}/",
102 |       binary: false
103 |     )
104 |   end
105 | 
106 |   def create_folder_feed_item(conference, content: '', identifier: 'podcast', extension: 'xml')
107 |     @items << Nanoc3::Item.new(
108 |       content,
109 |       {
110 |         extension: extension
111 |       },
112 |       get_path(conference.webgen_location, identifier),
113 |       binary: false
114 |     )
115 |   end
116 | 
117 |   private
118 | 
119 |   def event_attributes(event)
120 |     {
121 |       title: event.title,
122 |       tags: event.tags.map { |t| t.strip },
123 |       conference: event.conference,
124 |       event: event,
125 |       video_recordings: event.recordings.downloaded.video,
126 |       audio_recordings: event.recordings.downloaded.audio
127 |     }
128 |   end
129 | 
130 |   def conference_title(conference)
131 |     if conference.title.present?
132 |       conference.title
133 |     else
134 |       conference.acronym
135 |     end
136 |   end
137 | 
138 |   def get_path(*parts)
139 |     raise "nil found in item path" if parts.any? { |p| p.nil? }
140 |     '/browse/' + parts.join('/') + '/'
141 |   end
142 | 
143 |   def sorting_events(events, criteria)
144 |     case criteria
145 |     when 'name'
146 |       events.sort_by{ |e| e.title }
147 |     when 'duration'
148 |       events.sort_by{ |e| e.recordings.downloaded.first.length.nil? ? 0 : e.recordings.downloaded.first.length }.reverse
149 |     when 'date'
150 |       events.sort_by{ |e| date(e) }
151 |     else
152 |       events
153 |     end
154 |   end
155 | 
156 | end
157 | 


--------------------------------------------------------------------------------
/lib/data_source/location_pages.rb:
--------------------------------------------------------------------------------
 1 | class LocationPages
 2 |   def initialize
 3 |     @locations = Hash.new(0)
 4 |   end
 5 | 
 6 |   def add(location)
 7 |     @locations[location] += 1
 8 |   end
 9 | 
10 |   def apply(item_builder)
11 |     locations = @locations.keys
12 | 
13 |     root = build_navigation_tree(locations)
14 |     walk_navigation_paths(root, []) { |path, childs|
15 |       # skip last node
16 |       next if locations.include? path
17 |       item_builder.create_browse_item(path, childs)
18 |     }
19 | 
20 |     item_builder.create_browse_item('/', root.keys)
21 |   end
22 | 
23 |   def duplicate?
24 |     @locations.any? { |k,v| v > 1 }
25 |   end
26 | 
27 |   private
28 | 
29 |   def build_navigation_tree(locations)
30 |     root = {}
31 |     locations.each { |location|
32 |       node = root
33 |       next if location.nil?
34 |       location.split(%r{/}).each { |path| 
35 |         node[path] ||= {}
36 |         node = node[path]
37 |       }
38 |     }
39 |     root
40 |   end
41 | 
42 |   def walk_navigation_paths(root, paths, &block)
43 |     root.each { |k,leafs|
44 |       p = paths.clone
45 |       p << k
46 |       block.call p.join('/'), leafs.keys
47 |       walk_navigation_paths(leafs, p, &block)
48 |     }
49 |   end
50 | 
51 | end
52 | 


--------------------------------------------------------------------------------
/lib/data_source/tag_pages.rb:
--------------------------------------------------------------------------------
 1 | class TagPages
 2 | 
 3 |   def initialize
 4 |     @tags = Hash.new { |h,k| h[k] = [] }
 5 |   end
 6 |   attr_reader :tags
 7 | 
 8 |   def add(events)
 9 |     events.each { |event|
10 |       event.tags.each { |tag|
11 |         @tags[tag.strip] << event
12 |       }
13 |     }
14 |   end
15 | 
16 |   def apply(item_builder)
17 |     @tags.each { |tag, events|
18 |       item_builder.create_tag_item(tag, events)
19 |     }
20 |   end
21 | 
22 | end
23 | 


--------------------------------------------------------------------------------
/lib/default.rb:
--------------------------------------------------------------------------------
1 | # All files in the 'lib' directory will be loaded
2 | # before nanoc starts compiling.
3 | require 'ostruct'
4 | require 'json'
5 | require 'haml'
6 | Settings = OpenStruct.new JSON.load(File.open('settings.json')) unless defined? Settings
7 | 


--------------------------------------------------------------------------------
/lib/feeds.rb:
--------------------------------------------------------------------------------
1 | module Feeds
2 |   load 'lib/feeds/helper.rb'
3 | end
4 | 


--------------------------------------------------------------------------------
/lib/feeds/broadcatching.xml.haml:
--------------------------------------------------------------------------------
 1 | !!! XML
 2 | %rss{version: '2.0', 'xmlns:dc' => 'http://purl.org/dc/elements/1.1/'}
 3 |   %channel
 4 |     %title= config['channel_title']
 5 |     %link= "http#{config['base_url']}"
 6 |     %description= config['channel_description']
 7 |     %language= 'en-us, de-de'
 8 |     %pubDate= Time.now
 9 |     %lastBuildDate= Time.now
10 |     %docs http://blogs.law.harvard.edu/tech/rss
11 |     - events.each do |event|
12 |       - recording = event.public_send query, mime_type: config[:mime_type]
13 |       - if recording
14 |         %item
15 |           %title= ""
16 |           %link= "#{recording.try(:url)}?torrent"
17 |           %pubDate= event.date.to_s || event.created_at.to_s
18 |           %category= ""
19 |           %dc:creator= ""
20 |           %guid= recording.try(:url)
21 |           %torrent{'xmlns' => 'http://xmlns.ezrss.it/0.1/'}
22 |             %infoHash= recording.magnet_info_hash
23 |             %magnetURI= ""
24 | 


--------------------------------------------------------------------------------
/lib/feeds/broadcatching_generator.rb:
--------------------------------------------------------------------------------
 1 | # generate torrent broadcatching feeds for folders
 2 | module Feeds
 3 |   module BroadcatchingGenerator
 4 | 
 5 |     def self.generate(events: [], query: nil, config: {})
 6 |       rss = BroadcatchingGenerator::TorrentRSS.new config
 7 |       rss.generate events, query
 8 |     end
 9 | 
10 |     class TorrentRSS
11 |       include Feeds::Helper
12 | 
13 |       def initialize(config)
14 |         @config = OpenStruct.new Settings.feeds
15 |         merge_config(config)
16 |       end
17 |       attr_reader :config
18 |       attr_writer :config
19 | 
20 |       def generate(events, query)
21 |         template = File.read('lib/feeds/broadcatching.xml.haml')
22 |         haml_engine = Haml::Engine.new(template)
23 |         output = haml_engine.render(self, events: events, query: query, config: @config)
24 |         output
25 |       end
26 |     end
27 | 
28 |   end
29 | end
30 | 


--------------------------------------------------------------------------------
/lib/feeds/helper.rb:
--------------------------------------------------------------------------------
 1 | module Feeds
 2 | 
 3 |   module Helper
 4 | 
 5 |     def merge_config(config)
 6 |       keep = [ :title, :channel_summary ]
 7 |       @config.channel_title = [ @config.channel_title, config[:title] ].join(' - ')
 8 |       @config.channel_summary += config[:channel_summary]
 9 | 
10 |       config.each { |k,v|
11 |         next if keep.include? k
12 |         @config[k] = v
13 |       }
14 |     end
15 | 
16 |     def get_item_title(event)
17 |       conference = event.conference
18 |       title = ''
19 |       if conference.title.present?
20 |         title = conference.title
21 |       elsif conference.acronym.present?
22 |         title = conference.acronym
23 |       end
24 |       title += ": "
25 |       if event.title
26 |         title += event.title
27 |       else
28 |         title += event.slug
29 |       end
30 |       title
31 |     end
32 | 
33 |     def get_item_description(event)
34 |       description = []
35 |       description << event.description or event.subtitle
36 | 
37 |       link = event.link
38 |       description << "about this event: #{link}\n" if link
39 | 
40 |       # file = 'src/browse/bla.page'
41 |       url = @config['base_url'] + event.slug + '.html'
42 |       description << "event on media: #{url}\n"
43 | 
44 |       description.join
45 |     end
46 | 
47 |   end
48 | 
49 | end
50 | 


--------------------------------------------------------------------------------
/lib/feeds/newsfeed_generator.rb:
--------------------------------------------------------------------------------
 1 | require 'rss/maker'
 2 | 
 3 | module Feeds
 4 |   # Atom news feed generator.
 5 |   module NewsFeedGenerator
 6 | 
 7 |     # Generate atom feed for given news.
 8 |     #
 9 |     # @example Generate atom feed for given news
10 |     #   news = News.all
11 |     #   Feeds::NewsFeedGenerator.generate(news)
12 |     #     #=> "\n] should be generate to an atom feed
15 |     # @param options [Hash] to define feed preferences
16 |     # @option opts [String] :author Feed author
17 |     # @option opts [String] :about Feed about text
18 |     # @option opts [String] :title Feed title
19 |     #
20 |     # @return [String] atom feed
21 |     def self.generate(news, options: {})
22 |       atom_feed = build_feed(news, options)
23 |       atom_feed.to_s
24 |     end
25 | 
26 |     # Build atom feed object for given news.
27 |     #
28 |     # @example Generate atom feed object for given news
29 |     #   news = News.all
30 |     #   Feeds::NewsFeedGenerator.events(news) #=> #
31 |     #
32 |     # @param news [Array] to convert to an atom feed
33 |     # @param options [Hash] to define feed preferences
34 |     # @option opts [String] :author Feed author
35 |     # @option opts [String] :about Feed about text
36 |     # @option opts [String] :title Feed title
37 |     #
38 |     # @return [RSS::Atom::Feed] atom feed
39 |     def self.build_feed(news, options)
40 |       RSS::Maker.make('atom') do |feed|
41 |         assign_feed_options(feed, options)
42 | 
43 |         # Create feed item for every news
44 |         news.each do |news|
45 |           feed.items.new_item do |item|
46 |             assign_item_options(item, news)
47 |           end
48 |         end
49 | 
50 | 
51 |       end
52 |     end
53 | 
54 |     protected
55 | 
56 |     # Assign news options to an atom feed item.
57 |     #
58 |     # @param item [RSS::Maker::Atom::Feed::Items::Item]
59 |     # @param news [News] object
60 |     def self.assign_item_options(item, news)
61 |       item.id              = "tag:media.ccc.de,#{news.created_at.strftime('%Y-%m-%d')}:#{news.id}"
62 |       item.updated         = Time.now.to_s
63 |       item.title           = news.title
64 |       item.content.content = news.body
65 |       item.content.type    = 'html'
66 |       item.published       = news.created_at
67 |       item.updated         = news.updated_at
68 |       item.link            = 'http://media.ccc.de/'
69 |     end
70 | 
71 |     # Assign options like a title or an author to an atom feed.
72 |     #
73 |     # @param feed [RSS::Maker::Atom::Feed] atom feed
74 |     # @param options [Hash] options
75 |     def self.assign_feed_options(feed, options)
76 |       feed.channel.author  = options[:author]
77 |       feed.channel.updated = Time.now.to_s
78 |       feed.channel.about   = options[:about]
79 |       feed.channel.title   = options[:title]
80 |       feed.channel.link    = options[:feed_url]
81 |       feed.channel.icon    = options[:icon]
82 |       feed.channel.logo    = options[:logo]
83 |       # define feed link attributes
84 |       feed.channel.links.first.rel  = 'self'
85 |       feed.channel.links.first.type = 'application/atom+xml'
86 |     end
87 |   end
88 | end
89 | 


--------------------------------------------------------------------------------
/lib/feeds/podcast_generator.rb:
--------------------------------------------------------------------------------
  1 | # generate iTunes store feed
  2 | module Feeds
  3 |   module PodcastGenerator
  4 | 
  5 |     def self.generate(events: [], query: nil, config: {})
  6 |       rss = PodcastGenerator::UpdatesITS.new config
  7 |       rss.generate events, query
  8 |     end
  9 | 
 10 |     class UpdatesITS
 11 |       require 'rss/2.0'
 12 |       require 'rss/itunes'
 13 |       require 'rss/maker'
 14 |       require 'rss/content'
 15 |       include Feeds::Helper
 16 | 
 17 |       def initialize(config)
 18 |         @config = OpenStruct.new Settings.feeds
 19 |         merge_config(config)
 20 |       end
 21 |       attr_reader :config
 22 |       attr_writer :config
 23 | 
 24 |       def generate(events, query)
 25 |         rss = RSS::Maker.make("2.0") do |maker|
 26 | 
 27 |           create_channel(maker)
 28 | 
 29 | 
 30 |           events.each do |event|
 31 | 
 32 |             recording = event.public_send query, mime_type: @config[:mime_type]
 33 |             next if recording.nil?
 34 | 
 35 |             fill_item(maker.items.new_item, event, recording)
 36 |           end
 37 | 
 38 |         end
 39 |         rss.to_s
 40 |       end
 41 | 
 42 |       private
 43 | 
 44 |       def create_channel(maker)
 45 |         maker.channel.title = @config['channel_title']
 46 |         maker.channel.link =  @config['base_url']
 47 |         maker.channel.description = @config['channel_description']
 48 |         maker.channel.copyright = "mostly cc-by-nc"
 49 |         maker.channel.language = "en-us, de-de"
 50 |         maker.channel.lastBuildDate = Time.now
 51 | 
 52 |         # see http://www.apple.com/itunes/podcasts/specs.html#category
 53 |         #category = maker.channel.itunes_categories.new_category
 54 |         #category.text = "Technology"
 55 |         #category.new_category.text = "Technology"
 56 |         maker.channel.itunes_categories.new_category.text = "Technology"
 57 | 
 58 |         # TODO png/jpg?
 59 |         maker.image.url = @config['logo_image']
 60 |         maker.image.title = @config['channel_title']
 61 |         maker.channel.itunes_author = @config['channel_owner']
 62 |         maker.channel.itunes_owner.itunes_name = @config['channel_owner']
 63 |         maker.channel.itunes_owner.itunes_email='media@koeln.ccc.de'
 64 |         maker.channel.itunes_keywords = @config['channel_keywords']
 65 |         maker.channel.itunes_subtitle = @config['channel_subtitle']
 66 |         maker.channel.itunes_summary = @config['channel_summary']
 67 | 
 68 |         maker.channel.itunes_image = @config['logo_image']
 69 |         maker.channel.itunes_explicit = "No"
 70 |       end
 71 | 
 72 |       def fill_item(item, event, recording)
 73 |         item.title = get_item_title(event)
 74 |         item.link = recording.url
 75 |         item.itunes_keywords = event.try(:tags).join(',')
 76 |         item.guid.content = recording.url
 77 |         item.guid.isPermaLink = true
 78 |         item.dc_identifier = event.guid
 79 | 
 80 |         # FIXME decode, redcloth, whatever
 81 |         description = get_item_description(event)
 82 |         item.description = description
 83 |         item.itunes_duration = Time.at(recording.length).utc.strftime "%H:%M:%S"
 84 |         item.itunes_summary = description
 85 |         item.itunes_explicit = "No"
 86 |         item.pubDate = event.created_at.to_s
 87 | 
 88 |         item.itunes_subtitle = event.subtitle if event.subtitle.present?
 89 |         item.itunes_author = event.persons.join(', ') if event.persons.present?
 90 |         item.pubDate = event.date.to_s if event.date.present?
 91 | 
 92 |         item.enclosure.url = recording.url
 93 |         item.enclosure.length = recording.size || 0
 94 |         item.enclosure.type = recording.display_mime_type
 95 |       end
 96 |     end
 97 | 
 98 |   end
 99 | end
100 | 


--------------------------------------------------------------------------------
/lib/feeds/rdf_generator.rb:
--------------------------------------------------------------------------------
 1 | # generate rssfeed from svn log
 2 | module Feeds
 3 |   module RDFGenerator
 4 | 
 5 |     def self.generate(events: [], config: {})
 6 |       rss = RDFGenerator::UpdatesRDF.new config
 7 |       rss.generate events
 8 |     end
 9 | 
10 |     class UpdatesRDF
11 |       require 'rss'
12 |       require 'rss/1.0'
13 |       require 'rss/maker'
14 |       require 'rss/content'
15 |       include Feeds::Helper
16 | 
17 |       def initialize(config)
18 |         @config = OpenStruct.new Settings.feeds
19 |         merge_config(config)
20 |       end
21 |       attr_reader :config
22 |       attr_writer :config
23 | 
24 |       def generate(events)
25 |         rss = RSS::Maker.make("1.0") do |maker|
26 | 
27 |           create_channel(maker)
28 | 
29 |           events.each do |event|
30 | 
31 |             recording = event.preferred_recording
32 |             next if recording.nil?
33 | 
34 |             fill_item(maker.items.new_item, event, recording)
35 |           end
36 | 
37 |         end
38 |         rss.to_s
39 |       end
40 | 
41 |       private
42 | 
43 |       def create_channel(maker)
44 |         maker.channel.title = @config.channel_title
45 |         maker.channel.about = File.join(@config.base_url, 'updates.rdf')
46 |         maker.channel.link = @config.base_url
47 |         maker.channel.description = @config.channel_description
48 |         maker.image.title = @config.channel_title
49 |         maker.image.url = @config.logo_image
50 |         #maker.items.do_sort = true
51 |       end
52 | 
53 |       def fill_item(item, event, recording)
54 |         item.link = recording.url
55 |         item.title = get_item_title(event)
56 |         item.description = get_item_description(event)
57 | 
58 |         item.content_encoded = <
60 |         #{item.description}
61 |
62 | Video:#{recording.filename} 63 | 64 | EOF 65 | item.pubDate = date(event) 66 | 67 | end 68 | 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /lib/helpers.rb: -------------------------------------------------------------------------------- 1 | include Nanoc::Helpers::Rendering 2 | include Nanoc::Helpers::Breadcrumbs 3 | include Nanoc::Helpers::XMLSitemap 4 | -------------------------------------------------------------------------------- /lib/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | require 'uri' 3 | require 'nanoc/helpers/html_escape' 4 | include Nanoc::Helpers::HTMLEscape 5 | 6 | def twitter_url(title, url) 7 | "http://twitter.com/home?status="+URI.encode_www_form_component(title+": "+url) 8 | end 9 | 10 | def facebook_url(title, url) 11 | "https://www.facebook.com/sharer/sharer.php?t="+URI.encode_www_form_component(title)+"&u="+URI.encode_www_form_component(url) 12 | end 13 | 14 | def googleplus_url(title, url) 15 | "https://plus.google.com/share?title="+URI.encode_www_form_component(title)+"&url="+URI.encode_www_form_component(url) 16 | end 17 | 18 | def appnet_url(title, url) 19 | "https://alpha.app.net/intent/post?text="+URI.encode_www_form_component(title+": "+url) 20 | end 21 | 22 | def mail_url(title, url) 23 | content = URI.encode_www_form_component(title+': '+url) 24 | subject = URI.encode_www_form_component(title) 25 | URI::MailTo.build(['', [['Subject', subject], ['Body', content]]]).to_s 26 | end 27 | 28 | def oembed_url(identifier) 29 | Settings.oembedURL + identifier[0..-2] + '.html' 30 | end 31 | 32 | def oembed_page_url(identifier) 33 | id = identifier+"oembed/" 34 | oembed = @items.find { |i| i.identifier == id } 35 | Settings.baseURL + oembed.path 36 | end 37 | 38 | def page_url(identifier) 39 | Settings.baseURL + identifier.path 40 | end 41 | 42 | def event_page_or_folder(item) 43 | return if @item.identifier.include? '/tags/' 44 | trail = breadcrumbs_trail 45 | return unless trail.count > 2 or @item.identifier.include? '/browse/' 46 | trail = trail[0..-2] if @item.identifier.include? '/download/' 47 | yield trail 48 | end 49 | 50 | def video_download_sources(recordings) 51 | skip = %w[vnd.voc/mp4-web vnd.voc/webm-web] 52 | recordings.reject { |r| skip.include? r.mime_type } 53 | end 54 | 55 | def video_tag_sources(recordings, order=MimeType::WEB_PREFERRED_VIDEO) 56 | scores = {} 57 | recordings.select { |r| order.include? r.mime_type }.each { |r| 58 | pos = order.index r.mime_type 59 | fail r.mime_type unless pos 60 | if scores.has_key? r.display_mime_type 61 | scores[r.display_mime_type] = pos unless scores[r.display_mime_type] < pos 62 | else 63 | scores[r.display_mime_type] = pos 64 | end 65 | } 66 | scores.map { |_, pos| 67 | mime_type = order[pos] 68 | recordings.detect { |r| r.mime_type == mime_type } 69 | } 70 | end 71 | 72 | def keywords 73 | if @item[:event] and @item[:event].tags 74 | [ @item[:event].tags, Settings.header['keywords']].join(', ') 75 | else 76 | Settings.header['keywords'] 77 | end 78 | end 79 | 80 | def recording_length(recordings) 81 | return unless recordings.present? 82 | recording = recordings.select { |r| r.length.present? }.first 83 | recording_length_minutes(recording) unless recording.nil? 84 | end 85 | 86 | def recording_length_minutes(recording) 87 | if recording.length > 0 88 | "#{recording.length / 60} min" 89 | end 90 | end 91 | 92 | def flash(recordings) 93 | url = recordings.select { |recording| recording.display_mime_type == 'video/mp4' }.first.try(:url) 94 | if url.present? 95 | h(url) 96 | elsif recordings.present? 97 | h(recordings.first.url) 98 | else 99 | # :( 100 | '' 101 | end 102 | end 103 | 104 | def aspect_ratio_width(high=true) 105 | conference = @item[:conference] 106 | case conference.aspect_ratio 107 | when /16:9/ 108 | high ? '640' : '188' 109 | when /4:3/ 110 | high ? '400' : '120' 111 | else 112 | end 113 | end 114 | 115 | def aspect_ratio_height(high=true) 116 | conference = @item[:conference] 117 | case conference.aspect_ratio 118 | when /16:9/ 119 | high ? '360' : '144' 120 | when /4:3/ 121 | high ? '300' : '90' 122 | else 123 | end 124 | end 125 | 126 | def date(event) 127 | date = event.release_date || event.date 128 | date.strftime("%Y-%m-%d") if date 129 | end 130 | 131 | def datetime(event) 132 | date = event.release_date || event.date 133 | date.strftime("%Y-%m-%d %H:%M") if date 134 | end 135 | 136 | def parse_url_host(urlish) 137 | begin 138 | URI.parse(@item[:event].link).host() 139 | rescue URI::InvalidURIError 140 | return "" 141 | end 142 | end 143 | end 144 | -------------------------------------------------------------------------------- /lib/helpers/logo_filter_helper.rb: -------------------------------------------------------------------------------- 1 | class Thumbnailize < Nanoc::Filter 2 | 3 | identifier :logo 4 | type :binary 5 | 6 | def run(filename, params={}) 7 | system( 8 | 'gm', 9 | 'convert', 10 | filename, 11 | '-resize', 'x100', 12 | '-background', 'white', 13 | '-gravity', 'Center', 14 | '-extent', 'x100', 15 | '+profile', '*', 16 | output_filename 17 | ) 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /lib/helpers/tagging_helper.rb: -------------------------------------------------------------------------------- 1 | # Set the tags attribute on items to use this helper 2 | module TaggingHelper 3 | 4 | require 'nanoc/helpers/html_escape' 5 | include Nanoc::Helpers::HTMLEscape 6 | 7 | # link to tag page 8 | def link_for(tag, prefix: '/browse/tags/', css: '') 9 | %[] 10 | end 11 | 12 | # 13 | def tag_cloud(prefix: '/browse/tags/') 14 | return if @items.nil? 15 | tags_hash.map { |tag, count| 16 | link_for tag, prefix: prefix, css: css_class_by_size(count) 17 | } 18 | end 19 | 20 | private 21 | 22 | def css_class_by_size(n) 23 | if n < 5 24 | "xtiny" 25 | elsif n < 10 26 | "tiny" 27 | elsif n < 50 28 | "normal" 29 | elsif n < 100 30 | "large" 31 | else 32 | "xlarge" 33 | end 34 | end 35 | 36 | def tags_hash 37 | tags = Hash.new { |h,k| h[k] = [] } 38 | @items.each do |i| 39 | next unless i[:tag] 40 | tags[i[:title]] = i[:events].count 41 | end 42 | tags 43 | end 44 | 45 | end 46 | -------------------------------------------------------------------------------- /lib/helpers_.rb: -------------------------------------------------------------------------------- 1 | # from nanocs documentation: 2 | # the underscore is necessary to ensure that the file is loaded after the helpers are loaded, which is necessary because files in lib/ are loaded in alphabetical order 3 | include ApplicationHelper 4 | include TaggingHelper 5 | -------------------------------------------------------------------------------- /lib/magnet_link_provider.rb: -------------------------------------------------------------------------------- 1 | class MagnetLinkProvider 2 | include Singleton 3 | 4 | def fetch(recording) 5 | begin 6 | magnet = download(recording).chomp 7 | [magnet[20..59], magnet.to_s] 8 | rescue OpenURI::HTTPError => ex 9 | STDERR.puts "Failed to download URL #{recording.url} : #{ex.message}" 10 | [nil,nil] 11 | end 12 | end 13 | 14 | private 15 | 16 | def cache 17 | @cache ||= ActiveSupport::Cache.lookup_store(:file_store, 'tmp/cache_magnets') 18 | end 19 | 20 | def download(recording) 21 | cache.fetch(cache_key(:magnet, recording)) do 22 | #`curl #{recording.url}?magnet` 23 | download_uri("#{recording.url}?magnet") 24 | end 25 | end 26 | 27 | def cache_key(identifier, model) 28 | identifier.to_s + '_' + Digest::SHA1.hexdigest([model.id, model.updated_at.to_i].join(';')) 29 | end 30 | 31 | def download_uri(url) 32 | content = '' 33 | url = url.gsub(/ /, '%20') 34 | uri = URI(URI.escape(url)) 35 | 36 | if uri.scheme.nil? 37 | uri = URI('https:' + uri.to_s) 38 | end 39 | 40 | if uri.scheme == 'file' 41 | File.open(uri.path, 'r:UTF-8') { |f| content = f.read } 42 | else 43 | content = open(url).read 44 | end 45 | content.to_s 46 | end 47 | end 48 | 49 | -------------------------------------------------------------------------------- /lib/mime_type.rb: -------------------------------------------------------------------------------- 1 | class MimeType 2 | HTML5 = %w[audio/ogg audio/mpeg audio/opus video/mp4 video/ogg video/webm vnd.voc/h264-lq vnd.voc/h264-sd vnd.voc/webm-hd vnd.voc/h264-hd] 3 | PREFERRED_VIDEO = %w[vnd.voc/h264-hd vnd.voc/h264-lq video/mp4 vnd.voc/h264-sd vnd.voc/webm-hd video/webm video/ogg] 4 | WEB_PREFERRED_VIDEO = %w[vnd.voc/mp4-web vnd.voc/webm-web vnd.voc/h264-hd vnd.voc/h264-lq video/mp4 vnd.voc/h264-sd vnd.voc/webm-hd video/webm video/ogg] 5 | 6 | class << self 7 | 8 | def mime_type_slug(mime_type) 9 | humanized_mime_type(mime_type).to_param.downcase 10 | end 11 | 12 | def display_mime_type(mime_type) 13 | case mime_type 14 | when 'vnd.voc/h264-lq' 15 | 'video/mp4' 16 | when 'vnd.voc/h264-sd' 17 | 'video/mp4' 18 | when 'vnd.voc/h264-hd' 19 | 'video/mp4' 20 | when 'vnd.voc/mp4-web' 21 | 'video/mp4' 22 | when 'vnd.voc/webm-hd' 23 | 'video/webm' 24 | when 'vnd.voc/webm-web' 25 | 'video/webm' 26 | else 27 | mime_type 28 | end 29 | end 30 | 31 | def hd?(mime_type) 32 | case mime_type 33 | when 'vnd.voc/h264-lq' 34 | false 35 | when 'vnd.voc/h264-sd' 36 | false 37 | when 'vnd.voc/h264-hd' 38 | true 39 | when 'vnd.voc/webm-hd' 40 | true 41 | else 42 | nil 43 | end 44 | end 45 | 46 | def humanized_mime_type(mime_type) 47 | case mime_type 48 | when 'vnd.voc/h264-lq' 49 | 'MP4 (LQ)' 50 | when 'vnd.voc/h264-sd' 51 | 'MP4 (SD)' 52 | when 'vnd.voc/h264-hd' 53 | 'MP4 (HD)' 54 | when 'vnd.voc/webm-hd' 55 | 'WEBM (HD)' 56 | when 'vnd.voc/webm-web' 57 | 'WEBM (html5)' 58 | when 'vnd.voc/mp4-web' 59 | 'MP4 (html5)' 60 | when 'audio/mpeg' 61 | 'MP3' 62 | else 63 | mime_type.split('/')[1] 64 | end 65 | end 66 | 67 | end 68 | 69 | end 70 | -------------------------------------------------------------------------------- /lib/models/conference.rb: -------------------------------------------------------------------------------- 1 | class Conference < ActiveRecord::Base 2 | has_many :events 3 | 4 | def mime_types 5 | Recording.recorded_at(self).pluck(:mime_type).uniq.map { |mime_type| 6 | yield mime_type, MimeType.mime_type_slug(mime_type) 7 | } 8 | end 9 | 10 | def preferred_mime_type 11 | available = Recording.recorded_at(self).pluck(:mime_type).uniq 12 | MimeType::PREFERRED_VIDEO.each { |mime_type| 13 | return MimeType.mime_type_slug(mime_type) if available.include? mime_type 14 | } 15 | return MimeType.mime_type_slug(available.first) 16 | end 17 | 18 | def recordings_url 19 | File.join Settings.cdnURL, self.recordings_path 20 | end 21 | 22 | def logo_url 23 | if self.logo 24 | File.join '/images/logos', self.images_path, File.basename(self.logo, File.extname(self.logo))+'.png' 25 | else 26 | File.join '/images/logos/unknown.png' 27 | end 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /lib/models/event.rb: -------------------------------------------------------------------------------- 1 | class Event < ActiveRecord::Base 2 | belongs_to :conference 3 | has_many :recordings 4 | 5 | serialize :persons, Array 6 | serialize :tags, Array 7 | 8 | scope :promoted, ->(n) { where(promoted: true).order('updated_at desc').limit(n) } 9 | scope :recent, ->(n) { order('release_date desc').limit(n) } 10 | scope :newer, ->(date) { where("release_date > ?", date).order('release_date desc') } 11 | scope :older, ->(date) { where("release_date < ?", date).order('release_date desc') } 12 | 13 | scope :recorded_at, ->(conference) { 14 | joins(:recordings, :conference) 15 | .where(conferences: { id: conference }) 16 | .where(recordings: { state: 'downloaded', mime_type: MimeType::HTML5 }) 17 | .group(:"events.id") 18 | } 19 | 20 | def title 21 | read_attribute(:title).strip 22 | end 23 | 24 | def url 25 | "/browse/#{self.conference.webgen_location}/#{self.slug}.html" 26 | end 27 | 28 | def download_url 29 | "/browse/#{self.conference.webgen_location}/#{self.slug}/download.html#download" 30 | end 31 | 32 | def poster_url 33 | File.join(Settings.staticURL, 'media', self.conference.images_path, self.poster_filename) if self.poster_filename 34 | end 35 | 36 | def thumb_url 37 | File.join Settings.staticURL, 'media', self.conference.images_path, self.thumb_filename 38 | end 39 | 40 | def tags 41 | read_attribute(:tags).compact.collect { |x| x.strip } 42 | end 43 | 44 | def persons_text 45 | if self.persons.length == 0 46 | 'n/a' 47 | elsif self.persons.length == 1 48 | self.persons[0] 49 | else 50 | persons = self.persons[0..-3] + [self.persons[-2..-1].join(' and ')] 51 | persons.join(', ') 52 | end 53 | end 54 | 55 | def linked_persons_text 56 | if self.persons.length == 0 57 | 'n/a' 58 | elsif self.persons.length == 1 59 | linkify_persons(self.persons)[0] 60 | else 61 | persons = linkify_persons(self.persons) 62 | persons = persons[0..-3] + [persons[-2..-1].join(' and ')] 63 | persons.join(', ') 64 | end 65 | end 66 | 67 | def linkify_persons(persons) 68 | persons.map { |person| ''+CGI.escapeHTML(person)+'' } 69 | end 70 | 71 | def persons_icon 72 | if self.persons.length <= 1 73 | 'fa-user' 74 | else 75 | 'fa-group' 76 | end 77 | end 78 | 79 | def preferred_recording(order: MimeType::PREFERRED_VIDEO, mime_type: nil) 80 | recordings = recordings_by_mime_type 81 | return if recordings.empty? 82 | order.each { |mt| 83 | return recordings[mt] if recordings.has_key?(mt) 84 | } 85 | recordings.first[1] 86 | end 87 | 88 | def by_mime_type(order: nil, mime_type: 'video/mp4') 89 | recordings.downloaded.by_mime_type(mime_type).first 90 | end 91 | 92 | private 93 | 94 | def recordings_by_mime_type 95 | Hash[recordings.downloaded.map { |r| [r.mime_type, r] }] 96 | end 97 | 98 | end 99 | -------------------------------------------------------------------------------- /lib/models/folder.rb: -------------------------------------------------------------------------------- 1 | class Folder 2 | def initialize(location:nil) 3 | @location = location 4 | end 5 | attr_accessor :location, :conference 6 | 7 | def name 8 | File.basename @location 9 | end 10 | 11 | def url 12 | "/browse/#{@location}/index.html" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/models/news.rb: -------------------------------------------------------------------------------- 1 | class News < ActiveRecord::Base 2 | scope :recent, ->(n) { order('date desc').limit(n) } 3 | 4 | def date_formatted 5 | self.date.strftime("%d.%m.%Y") 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/models/recording.rb: -------------------------------------------------------------------------------- 1 | class Recording < ActiveRecord::Base 2 | belongs_to :event 3 | 4 | scope :downloaded, -> { where(state: 'downloaded') } 5 | scope :by_mime_type, ->(mime_type) { where(mime_type: mime_type) } 6 | scope :audio, -> { where(mime_type: %w[audio/ogg audio/mpeg audio/opus]) } 7 | scope :video, -> { where(mime_type: %w[vnd.voc/mp4-web vnd.voc/webm-web video/mp4 vnd.voc/h264-lq vnd.voc/h264-hd vnd.voc/h264-sd vnd.voc/webm-hd video/ogg video/webm]) } 8 | scope :recorded_at, ->(conference) { joins(event: :conference).where(events: {'conference_id' => conference} ) } 9 | 10 | def url 11 | File.join self.event.conference.recordings_url, self.folder || '', self.filename 12 | end 13 | 14 | def torrent_url 15 | url + '.torrent' 16 | end 17 | 18 | def display_mime_type 19 | MimeType.display_mime_type(mime_type) 20 | end 21 | 22 | def filetype 23 | MimeType.humanized_mime_type(mime_type) 24 | end 25 | 26 | def magnet_uri 27 | _, link = torrent_magnet_data 28 | link 29 | end 30 | 31 | def magnet_info_hash 32 | hash, _ = torrent_magnet_data 33 | hash 34 | end 35 | 36 | private 37 | 38 | def torrent_magnet_data 39 | MagnetLinkProvider.instance.fetch self 40 | end 41 | 42 | end 43 | -------------------------------------------------------------------------------- /nanoc.yaml.example: -------------------------------------------------------------------------------- 1 | # A list of file extensions that nanoc will consider to be textual rather than 2 | # binary. If an item with an extension not in this list is found, the file 3 | # will be considered as binary. 4 | text_extensions: [ 'coffee', 'css', 'erb', 'haml', 'handlebars', 'hb', 'htm', 'html', 'js', 'less', 'markdown', 'md', 'ms', 'mustache', 'php', 'rb', 'sass', 'scss', 'txt', 'xhtml', 'xml', 'atom' ] 5 | 6 | # The path to the directory where all generated files will be written to. This 7 | # can be an absolute path starting with a slash, but it can also be path 8 | # relative to the site directory. 9 | output_dir: output 10 | encoding: utf-8 11 | 12 | # sitemap.xml 13 | base_url: http://media.ccc.de 14 | 15 | # A list of index filenames, i.e. names of files that will be served by a web 16 | # server when a directory is requested. Usually, index files are named 17 | # “index.html”, but depending on the web server, this may be something else, 18 | # such as “default.htm”. This list is used by nanoc to generate pretty URLs. 19 | index_filenames: [ 'index.html' ] 20 | 21 | # Whether or not to generate a diff of the compiled content when compiling a 22 | # site. The diff will contain the differences between the compiled content 23 | # before and after the last site compilation. 24 | enable_output_diff: false 25 | 26 | prune: 27 | # Whether to automatically remove files not managed by nanoc from the output 28 | # directory. For safety reasons, this is turned off by default. 29 | auto_prune: false 30 | 31 | # Which files and directories you want to exclude from pruning. If you version 32 | # your output directory, you should probably exclude VCS directories such as 33 | # .git, .svn etc. 34 | exclude: [ '.git', '.hg', '.svn', 'CVS' ] 35 | 36 | # The data sources where nanoc loads its data from. This is an array of 37 | # hashes; each array element represents a single data source. By default, 38 | # there is only a single data source that reads data from the “content/” and 39 | # “layout/” directories in the site directory. 40 | data_sources: 41 | - 42 | # The type is the identifier of the data source. By default, this will be 43 | # `filesystem_unified`. 44 | type: filesystem_unified 45 | 46 | # The path where items should be mounted (comparable to mount points in 47 | # Unix-like systems). This is “/” by default, meaning that items will have 48 | # “/” prefixed to their identifiers. If the items root were “/en/” 49 | # instead, an item at content/about.html would have an identifier of 50 | # “/en/about/” instead of just “/about/”. 51 | items_root: / 52 | 53 | # The path where layouts should be mounted. The layouts root behaves the 54 | # same as the items root, but applies to layouts rather than items. 55 | layouts_root: / 56 | 57 | # nanoc defaults to environment input encoding 58 | # for the sake of windows users use utf-8 *everywhere* 59 | encoding: utf-8 60 | 61 | # Whether to allow periods in identifiers. When turned off, everything 62 | # past the first period is considered to be the extension, and when 63 | # turned on, only the characters past the last period are considered to 64 | # be the extension. For example, a file named “content/about.html.erb” 65 | # will have the identifier “/about/” when turned off, but when turned on 66 | # it will become “/about.html/” instead. 67 | allow_periods_in_identifiers: false 68 | - 69 | type: static 70 | items_root: /assets/ 71 | - 72 | type: static 73 | items_root: /images/ 74 | prefix: images 75 | - 76 | type: media_backend 77 | 78 | database: 79 | adapter: 'sqlite3' 80 | database: 'development.sqlite3' 81 | encoding: utf8 82 | -------------------------------------------------------------------------------- /settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseURL": "//media.ccc.de", 3 | "oembedURL": "//api.media.ccc.de/public/oembed?url=http://media.ccc.de", 4 | "cdnURL": "https://cdn.media.ccc.de", 5 | "staticURL": "//static.media.ccc.de", 6 | "header": { 7 | "description": "Video Streaming Portal des Chaos Computer Clubs", 8 | "author": "CCC", 9 | "google": "2ozQIr-cQ-sJzGeJT_iTkS147fs3c5R3I1i6Dk_YLwA", 10 | "keywords": "Chaos Computer Club, Video, Media, Streaming, TV, Hacker" 11 | }, 12 | "feeds": { 13 | "base_url": "//media.ccc.de/", 14 | "channel_title": "Chaos Computer Club", 15 | "channel_subtitle": "A wide variety of video material distributed by the CCC. All content is taken from cdn.media.ccc.de and media.ccc.de", 16 | "channel_description": "Der Chaos Computer Club ist die größte europäische Hackervereinigung, und seit über 25 Jahren Vermittler im Spannungsfeld technischer und sozialer Entwicklungen.", 17 | "channel_summary": "A wide variety of video material distributed by the Chaos Computer Club.", 18 | "channel_owner": "CCC media team", 19 | "logo_image": "//media.ccc.de/images/miro-banner.png", 20 | "channel_keywords": "CCC Congress Hacking Security Netzpolitik" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /static/css/bigplay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/css/bigplay.png -------------------------------------------------------------------------------- /static/css/bigplay.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/css/controls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/css/controls.png -------------------------------------------------------------------------------- /static/css/controls.svg: -------------------------------------------------------------------------------- 1 | cc -------------------------------------------------------------------------------- /static/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.1.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"} -------------------------------------------------------------------------------- /static/css/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/css/loading.gif -------------------------------------------------------------------------------- /static/css/mediaelementplayer.min.css: -------------------------------------------------------------------------------- 1 | .mejs-container{position:relative;background:#000;font-family:Helvetica,Arial;text-align:left;vertical-align:top;text-indent:0;}.me-plugin{position:absolute;}.mejs-embed,.mejs-embed body{width:100%;height:100%;margin:0;padding:0;background:#000;overflow:hidden;}.mejs-fullscreen{overflow:hidden!important;}.mejs-container-fullscreen{position:fixed;left:0;top:0;right:0;bottom:0;overflow:hidden;z-index:1000;}.mejs-container-fullscreen .mejs-mediaelement,.mejs-container-fullscreen video{width:100%;height:100%;}.mejs-clear{clear:both;}.mejs-background{position:absolute;top:0;left:0;}.mejs-mediaelement{position:absolute;top:0;left:0;width:100%;height:100%;}.mejs-poster{position:absolute;top:0;left:0;background-size:contain;background-position:50% 50%;background-repeat:no-repeat;}:root .mejs-poster img{display:none;}.mejs-poster img{border:0;padding:0;border:0;}.mejs-overlay{position:absolute;top:0;left:0;}.mejs-overlay-play{cursor:pointer;}.mejs-overlay-button{position:absolute;top:50%;left:50%;width:100px;height:100px;margin:-50px 0 0 -50px;background:url(bigplay.svg) no-repeat;}.no-svg .mejs-overlay-button{background-image:url(bigplay.png);}.mejs-overlay:hover .mejs-overlay-button{background-position:0 -100px;}.mejs-overlay-loading{position:absolute;top:50%;left:50%;width:80px;height:80px;margin:-40px 0 0 -40px;background:#333;background:url(background.png);background:rgba(0,0,0,0.9);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.9)),to(rgba(0,0,0,0.9)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-moz-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-o-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-ms-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:linear-gradient(rgba(50,50,50,0.9),rgba(0,0,0,0.9));}.mejs-overlay-loading span{display:block;width:80px;height:80px;background:transparent url(loading.gif) 50% 50% no-repeat;}.mejs-container .mejs-controls{position:absolute;list-style-type:none;margin:0;padding:0;bottom:0;left:0;background:url(background.png);background:rgba(0,0,0,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.7)),to(rgba(0,0,0,0.7)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-moz-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-o-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-ms-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:linear-gradient(rgba(50,50,50,0.7),rgba(0,0,0,0.7));height:30px;width:100%;}.mejs-container .mejs-controls div{list-style-type:none;background-image:none;display:block;float:left;margin:0;padding:0;width:26px;height:26px;font-size:11px;line-height:11px;font-family:Helvetica,Arial;border:0;}.mejs-controls .mejs-button button{cursor:pointer;display:block;font-size:0;line-height:0;text-decoration:none;margin:7px 5px;padding:0;position:absolute;height:16px;width:16px;border:0;background:transparent url(controls.svg) no-repeat;}.no-svg .mejs-controls .mejs-button button{background-image:url(controls.png);}.mejs-controls .mejs-button button:focus{outline:dotted 1px #999;}.mejs-container .mejs-controls .mejs-time{color:#fff;display:block;height:17px;width:auto;padding:8px 3px 0 3px;overflow:hidden;text-align:center;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}.mejs-container .mejs-controls .mejs-time span{color:#fff;font-size:11px;line-height:12px;display:block;float:left;margin:1px 2px 0 0;width:auto;}.mejs-controls .mejs-play button{background-position:0 0;}.mejs-controls .mejs-pause button{background-position:0 -16px;}.mejs-controls .mejs-stop button{background-position:-112px 0;}.mejs-controls div.mejs-time-rail{direction:ltr;width:200px;padding-top:5px;}.mejs-controls .mejs-time-rail span{display:block;position:absolute;width:180px;height:10px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;cursor:pointer;}.mejs-controls .mejs-time-rail .mejs-time-total{margin:5px;background:#333;background:rgba(50,50,50,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(30,30,30,0.8)),to(rgba(60,60,60,0.8)));background:-webkit-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-moz-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-o-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-ms-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:linear-gradient(rgba(30,30,30,0.8),rgba(60,60,60,0.8));}.mejs-controls .mejs-time-rail .mejs-time-buffering{width:100%;background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:15px 15px;-moz-background-size:15px 15px;-o-background-size:15px 15px;background-size:15px 15px;-webkit-animation:buffering-stripes 2s linear infinite;-moz-animation:buffering-stripes 2s linear infinite;-ms-animation:buffering-stripes 2s linear infinite;-o-animation:buffering-stripes 2s linear infinite;animation:buffering-stripes 2s linear infinite;}@-webkit-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-moz-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-ms-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-o-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}.mejs-controls .mejs-time-rail .mejs-time-loaded{background:#3caac8;background:rgba(60,170,200,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(44,124,145,0.8)),to(rgba(78,183,212,0.8)));background:-webkit-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-moz-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-o-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-ms-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:linear-gradient(rgba(44,124,145,0.8),rgba(78,183,212,0.8));width:0;}.mejs-controls .mejs-time-rail .mejs-time-current{background:#fff;background:rgba(255,255,255,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(255,255,255,0.9)),to(rgba(200,200,200,0.8)));background:-webkit-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-moz-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-o-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-ms-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:linear-gradient(rgba(255,255,255,0.9),rgba(200,200,200,0.8));width:0;}.mejs-controls .mejs-time-rail .mejs-time-handle{display:none;position:absolute;margin:0;width:10px;background:#fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;cursor:pointer;border:solid 2px #333;top:-2px;text-align:center;}.mejs-controls .mejs-time-rail .mejs-time-float{position:absolute;display:none;background:#eee;width:36px;height:17px;border:solid 1px #333;top:-26px;margin-left:-18px;text-align:center;color:#111;}.mejs-controls .mejs-time-rail .mejs-time-float-current{margin:2px;width:30px;display:block;text-align:center;left:0;}.mejs-controls .mejs-time-rail .mejs-time-float-corner{position:absolute;display:block;width:0;height:0;line-height:0;border:solid 5px #eee;border-color:#eee transparent transparent transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:15px;left:13px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float{width:48px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-current{width:44px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-corner{left:18px;}.mejs-controls .mejs-fullscreen-button button{background-position:-32px 0;}.mejs-controls .mejs-unfullscreen button{background-position:-32px -16px;}.mejs-controls .mejs-mute button{background-position:-16px -16px;}.mejs-controls .mejs-unmute button{background-position:-16px 0;}.mejs-controls .mejs-volume-button{position:relative;}.mejs-controls .mejs-volume-button .mejs-volume-slider{display:none;height:115px;width:25px;background:url(background.png);background:rgba(50,50,50,0.7);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:-115px;left:0;z-index:1;position:absolute;margin:0;}.mejs-controls .mejs-volume-button:hover{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-total{position:absolute;left:11px;top:8px;width:2px;height:100px;background:#ddd;background:rgba(255,255,255,0.5);margin:0;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-current{position:absolute;left:11px;top:8px;width:2px;height:100px;background:#ddd;background:rgba(255,255,255,0.9);margin:0;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-handle{position:absolute;left:4px;top:-3px;width:16px;height:6px;background:#ddd;background:rgba(255,255,255,0.9);cursor:N-resize;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;margin:0;}.mejs-controls div.mejs-horizontal-volume-slider{height:26px;width:60px;position:relative;}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total{position:absolute;left:0;top:11px;width:50px;height:8px;margin:0;padding:0;font-size:1px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#333;background:rgba(50,50,50,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(30,30,30,0.8)),to(rgba(60,60,60,0.8)));background:-webkit-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-moz-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-o-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-ms-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:linear-gradient(rgba(30,30,30,0.8),rgba(60,60,60,0.8));}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current{position:absolute;left:0;top:11px;width:50px;height:8px;margin:0;padding:0;font-size:1px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#fff;background:rgba(255,255,255,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(255,255,255,0.9)),to(rgba(200,200,200,0.8)));background:-webkit-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-moz-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-o-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-ms-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:linear-gradient(rgba(255,255,255,0.9),rgba(200,200,200,0.8));}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle{display:none;}.mejs-controls .mejs-captions-button{position:relative;}.mejs-controls .mejs-captions-button button{background-position:-48px 0;}.mejs-controls .mejs-captions-button .mejs-captions-selector{visibility:hidden;position:absolute;bottom:26px;right:-10px;width:130px;height:100px;background:url(background.png);background:rgba(50,50,50,0.7);border:solid 1px transparent;padding:10px;overflow:hidden;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul{margin:0;padding:0;display:block;list-style-type:none!important;overflow:hidden;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li{margin:0 0 6px 0;padding:0;list-style-type:none!important;display:block;color:#fff;overflow:hidden;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input{clear:both;float:left;margin:3px 3px 0 5px;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label{width:100px;float:left;padding:4px 0 0 0;line-height:15px;font-family:helvetica,arial;font-size:10px;}.mejs-controls .mejs-captions-button .mejs-captions-translations{font-size:10px;margin:0 0 5px 0;}.mejs-chapters{position:absolute;top:0;left:0;-xborder-right:solid 1px #fff;width:10000px;z-index:1;}.mejs-chapters .mejs-chapter{position:absolute;float:left;background:#222;background:rgba(0,0,0,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.7)),to(rgba(0,0,0,0.7)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-moz-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-o-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-ms-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:linear-gradient(rgba(50,50,50,0.7),rgba(0,0,0,0.7));filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,startColorstr=#323232,endColorstr=#000000);overflow:hidden;border:0;}.mejs-chapters .mejs-chapter .mejs-chapter-block{font-size:11px;color:#fff;padding:5px;display:block;border-right:solid 1px #333;border-bottom:solid 1px #333;cursor:pointer;}.mejs-chapters .mejs-chapter .mejs-chapter-block-last{border-right:none;}.mejs-chapters .mejs-chapter .mejs-chapter-block:hover{background:#666;background:rgba(102,102,102,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(102,102,102,0.7)),to(rgba(50,50,50,0.6)));background:-webkit-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-moz-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-o-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-ms-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:linear-gradient(rgba(102,102,102,0.7),rgba(50,50,50,0.6));filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,startColorstr=#666666,endColorstr=#323232);}.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title{font-size:12px;font-weight:bold;display:block;white-space:nowrap;text-overflow:ellipsis;margin:0 0 3px 0;line-height:12px;}.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan{font-size:12px;line-height:12px;margin:3px 0 4px 0;display:block;white-space:nowrap;text-overflow:ellipsis;}.mejs-captions-layer{position:absolute;bottom:0;left:0;text-align:center;line-height:22px;font-size:12px;color:#fff;}.mejs-captions-layer a{color:#fff;text-decoration:underline;}.mejs-captions-layer[lang=ar]{font-size:20px;font-weight:normal;}.mejs-captions-position{position:absolute;width:100%;bottom:15px;left:0;}.mejs-captions-position-hover{bottom:45px;}.mejs-captions-text{padding:3px 5px;background:url(background.png);background:rgba(20,20,20,0.8);}.me-cannotplay a{color:#fff;font-weight:bold;}.me-cannotplay span{padding:15px;display:block;}.mejs-controls .mejs-loop-off button{background-position:-64px -16px;}.mejs-controls .mejs-loop-on button{background-position:-64px 0;}.mejs-controls .mejs-backlight-off button{background-position:-80px -16px;}.mejs-controls .mejs-backlight-on button{background-position:-80px 0;}.mejs-controls .mejs-picturecontrols-button{background-position:-96px 0;}.mejs-contextmenu{position:absolute;width:150px;padding:10px;border-radius:4px;top:0;left:0;background:#fff;border:solid 1px #999;z-index:1001;}.mejs-contextmenu .mejs-contextmenu-separator{height:1px;font-size:0;margin:5px 6px;background:#333;}.mejs-contextmenu .mejs-contextmenu-item{font-family:Helvetica,Arial;font-size:12px;padding:4px 6px;cursor:pointer;color:#333;}.mejs-contextmenu .mejs-contextmenu-item:hover{background:#2C7C91;color:#fff;}.mejs-controls .mejs-sourcechooser-button{position:relative;}.mejs-controls .mejs-sourcechooser-button button{background-position:-128px 0;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector{visibility:hidden;position:absolute;bottom:26px;right:-10px;width:130px;height:100px;background:url(background.png);background:rgba(50,50,50,0.7);border:solid 1px transparent;padding:10px;overflow:hidden;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul{margin:0;padding:0;display:block;list-style-type:none!important;overflow:hidden;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li{margin:0 0 6px 0;padding:0;list-style-type:none!important;display:block;color:#fff;overflow:hidden;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input{clear:both;float:left;margin:3px 3px 0 5px;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label{width:100px;float:left;padding:4px 0 0 0;line-height:15px;font-family:helvetica,arial;font-size:10px;}.mejs-postroll-layer{position:absolute;bottom:0;left:0;width:100%;height:100%;background:url(background.png);background:rgba(50,50,50,0.7);z-index:1000;overflow:hidden;}.mejs-postroll-layer-content{width:100%;height:100%;}.mejs-postroll-close{position:absolute;right:0;top:0;background:url(background.png);background:rgba(50,50,50,0.7);color:#fff;padding:4px;z-index:100;cursor:pointer;} -------------------------------------------------------------------------------- /static/flashmediaelement.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/flashmediaelement.swf -------------------------------------------------------------------------------- /static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /static/fonts/bootstrap/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/bootstrap/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /static/fonts/bootstrap/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/bootstrap/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /static/fonts/bootstrap/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/bootstrap/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /static/fonts/estre.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/estre.eot -------------------------------------------------------------------------------- /static/fonts/estre.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/estre.otf -------------------------------------------------------------------------------- /static/fonts/estre.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/estre.ttf -------------------------------------------------------------------------------- /static/fonts/estre.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/estre.woff -------------------------------------------------------------------------------- /static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /static/js/purl.min.js: -------------------------------------------------------------------------------- 1 | /*! purl v2.3.1 | MIT */ 2 | (function(factory){if(typeof define==="function"&&define.amd){define(factory)}else{window.purl=factory()}})(function(){var tag2attr={a:"href",img:"src",form:"action",base:"href",script:"src",iframe:"src",link:"href"},key=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","fragment"],aliases={anchor:"fragment"},parser={strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/},isint=/^[0-9]+$/;function parseUri(url,strictMode){var str=decodeURI(url),res=parser[strictMode||false?"strict":"loose"].exec(str),uri={attr:{},param:{},seg:{}},i=14;while(i--){uri.attr[key[i]]=res[i]||""}uri.param["query"]=parseString(uri.attr["query"]);uri.param["fragment"]=parseString(uri.attr["fragment"]);uri.seg["path"]=uri.attr.path.replace(/^\/+|\/+$/g,"").split("/");uri.seg["fragment"]=uri.attr.fragment.replace(/^\/+|\/+$/g,"").split("/");uri.attr["base"]=uri.attr.host?(uri.attr.protocol?uri.attr.protocol+"://"+uri.attr.host:uri.attr.host)+(uri.attr.port?":"+uri.attr.port:""):"";return uri}function getAttrName(elm){var tn=elm.tagName;if(typeof tn!=="undefined")return tag2attr[tn.toLowerCase()];return tn}function promote(parent,key){if(parent[key].length===0)return parent[key]={};var t={};for(var i in parent[key])t[i]=parent[key][i];parent[key]=t;return t}function parse(parts,parent,key,val){var part=parts.shift();if(!part){if(isArray(parent[key])){parent[key].push(val)}else if("object"==typeof parent[key]){parent[key]=val}else if("undefined"==typeof parent[key]){parent[key]=val}else{parent[key]=[parent[key],val]}}else{var obj=parent[key]=parent[key]||[];if("]"==part){if(isArray(obj)){if(""!==val)obj.push(val)}else if("object"==typeof obj){obj[keys(obj).length]=val}else{obj=parent[key]=[parent[key],val]}}else if(~part.indexOf("]")){part=part.substr(0,part.length-1);if(!isint.test(part)&&isArray(obj))obj=promote(parent,key);parse(parts,obj,part,val)}else{if(!isint.test(part)&&isArray(obj))obj=promote(parent,key);parse(parts,obj,part,val)}}}function merge(parent,key,val){if(~key.indexOf("]")){var parts=key.split("[");parse(parts,parent,"base",val)}else{if(!isint.test(key)&&isArray(parent.base)){var t={};for(var k in parent.base)t[k]=parent.base[k];parent.base=t}if(key!==""){set(parent.base,key,val)}}return parent}function parseString(str){return reduce(String(str).split(/&|;/),function(ret,pair){try{pair=decodeURIComponent(pair.replace(/\+/g," "))}catch(e){}var eql=pair.indexOf("="),brace=lastBraceInKey(pair),key=pair.substr(0,brace||eql),val=pair.substr(brace||eql,pair.length);val=val.substr(val.indexOf("=")+1,val.length);if(key===""){key=pair;val=""}return merge(ret,key,val)},{base:{}}).base}function set(obj,key,val){var v=obj[key];if(typeof v==="undefined"){obj[key]=val}else if(isArray(v)){v.push(val)}else{obj[key]=[v,val]}}function lastBraceInKey(str){var len=str.length,brace,c;for(var i=0;i>0,curr=arguments[2];while(i ol > li.template').detach(), 10 | $noresults = $results.find('> ol > li.no-results').detach(), 11 | baseUrl = window.location.protocol+'//'+window.location.host+window.location.pathname, 12 | baseTitleTpl = $search.data('titletpl'), 13 | pageNr = 0, 14 | perPage = 15; 15 | 16 | $search 17 | .find('input.text') 18 | .focus() 19 | .end() 20 | .on('click', '.submit', function(e, triggerOrigin, displayPage) { 21 | e.preventDefault(); 22 | var 23 | $submit = $(this), 24 | $form = $submit.closest('form'), 25 | $input = $form.find('input.text'), 26 | term = $input.val(), 27 | lterm = term.toLowerCase(), 28 | title = baseTitleTpl.replace('#', $input.val()); 29 | 30 | displayPage = displayPage || 0; 31 | 32 | document.title = title; 33 | if(window.history && window.history.pushState) 34 | window.history.pushState({}, title, '?' + (displayPage > 0 ? 'p='+displayPage+'&' : '') + 'q='+encodeURIComponent(term)); 35 | 36 | $input.blur(); 37 | $('#media-search input[name=q]').val(term); 38 | $.ajax({ 39 | dataType: $.support.cors ? 'json' : 'jsonp', 40 | url: window.location.protocol+'//koeln.media.ccc.de/search/api/term', 41 | type: 'post', 42 | data: { 43 | term: lterm, 44 | displayPage: displayPage, 45 | perPage: perPage 46 | }, 47 | success: function(res) { 48 | var 49 | conferenceSearchBase = $template.find('.conference-search').data('titletpl'), 50 | eventSearchBase = $template.find('.event-search').data('titletpl'), 51 | $h1 = $search.find('form h1'), 52 | $list = $results 53 | .find('> ol') 54 | .attr('start', displayPage * perPage + 1) 55 | .find('> li') 56 | .remove() 57 | .end(); 58 | 59 | $h1.text($h1.data('resulttpl').replace('#', $input.val())); 60 | 61 | $statistics 62 | .find('.start') 63 | .text(displayPage * perPage + 1) 64 | .end() 65 | .find('.end') 66 | .text(displayPage * perPage + res.hits.hits.length) 67 | .end() 68 | .find('.total') 69 | .text(res.hits.total) 70 | .end() 71 | .find('.runtime') 72 | .text(res.took); 73 | 74 | $paging.toggleClass('visible', res.hits.total > res.hits.hits.length); 75 | if(res.hits.total > res.hits.hits.length) { 76 | $paging.find('li.page').remove(); 77 | var 78 | maxpages = res.hits.total / perPage, 79 | npages = Math.min(Math.max(10, displayPage+3), Math.ceil(maxpages)); 80 | 81 | for (var i = 0; i < npages; i++) { 82 | $pagingTemplate 83 | .clone() 84 | .removeClass('template') 85 | .toggleClass('active', i == displayPage) 86 | .find('a') 87 | .attr('href', '?p='+i+'&q='+encodeURIComponent(term)) 88 | .data('page', i) 89 | .end() 90 | .find('.number') 91 | .text(i+1) 92 | .end() 93 | .insertBefore($pagingPostfix); 94 | } 95 | 96 | $paging 97 | .find('.next') 98 | .toggleClass('visible', displayPage < maxpages-1) 99 | .find('> a') 100 | .attr('href', '?p='+(displayPage+1)+'&q='+encodeURIComponent(term)) 101 | .data('page', displayPage+1) 102 | .end() 103 | .end() 104 | .find('.prev') 105 | .toggleClass('visible', displayPage > 0) 106 | .find('> a') 107 | .attr('href', '?p='+(displayPage-1)+'&q='+encodeURIComponent(term)) 108 | .data('page', displayPage-1) 109 | } 110 | 111 | if(res.hits.hits.length == 0) { 112 | $noresults.appendTo($list); 113 | } 114 | else { 115 | jQuery.each(res.hits.hits, function(idx, hit) { 116 | var 117 | quality = hit._score * 100 / res.hits.max_score, 118 | logourl = hit._source.conference.logo; 119 | 120 | if(logourl.match(/\.(png|jpg|jpeg|gif)$/)) { 121 | logourl = logourl.replace('//static.media.ccc.de/media/', '/images/logos/'); 122 | logourl = logourl.substr(0, logourl.lastIndexOf('.')) + '.png'; 123 | } 124 | else { 125 | logourl = '/images/logos/unknown.png'; 126 | } 127 | 128 | 129 | var $item = $template 130 | .clone() 131 | .appendTo($list) 132 | .attr('data-quality', quality) // .data() does not show up in the DOM and this is mainly for debugging 133 | .addClass( 134 | quality > 80 ? 'high' : 135 | quality > 50 ? 'medium' : 136 | quality > 30 ? 'low' : 137 | 'nonsense' 138 | ) 139 | .removeClass('template') 140 | .find('h3 .number') 141 | .text(displayPage * perPage + 1 + idx) 142 | .end() 143 | .find('h3 .t') 144 | .text(hit._source.event.title) 145 | .end() 146 | .find('img.conference-logo') 147 | .attr('alt', hit._source.conference.title) 148 | .attr('src', logourl) 149 | .end() 150 | .find('a.conference-url') 151 | .attr('href', hit._source.event.frontend_link) 152 | .end() 153 | .find('.recording_length .t') 154 | .text(Math.round(parseInt(hit._source.event.length) / 60)+' min') 155 | .end() 156 | .find('.date .t') 157 | .text(hit._source.event.date) 158 | .end() 159 | .find('.persons .t') 160 | .html(personlinks(hit._source.event.persons)) 161 | .end() 162 | .find('.persons.fa') 163 | .addClass(hit._source.event.persons.length > 1 ? 'fa-group' : 'fa-user') 164 | .end(); 165 | }); 166 | } 167 | 168 | $form.addClass('fullsize'); 169 | window.scrollTo(0, 0); 170 | if(triggerOrigin == 'param') { 171 | $results.removeClass('initial'); 172 | } 173 | 174 | else if($form.hasClass('initial')) 175 | { 176 | $form.add($results).css({opacity: 0}).removeClass('initial').animate({ 177 | opacity: 1 178 | }) 179 | } 180 | } 181 | }); 182 | 183 | if(triggerOrigin == 'param') { 184 | $form.removeClass('initial'); 185 | } 186 | else if($form.hasClass('initial')) 187 | { 188 | $form.animate({ 189 | opacity: 0 190 | }, { 191 | duration: 0.75 192 | }) 193 | } 194 | }) 195 | .on('click', '.paging a', function(e) { 196 | e.preventDefault(); 197 | $search 198 | .find('.submit') 199 | .trigger('click', ['param', $(this).data('page')]); 200 | }); 201 | 202 | var param = $.url().param(); 203 | if(param.q) { 204 | $search 205 | .find('input.text') 206 | .val(param.q) 207 | .end() 208 | .find('.submit') 209 | .trigger('click', ['param', param.p]); 210 | } 211 | 212 | function personlinks(persons) { 213 | if(persons.length == 0) { 214 | return 'n/a'; 215 | } else if(persons.length < 3) { 216 | return linkify_personnames(persons).join(' and ') 217 | } else { 218 | return linkify_personnames(persons.slice(0, -2)).join(', ') + ', ' + linkify_personnames(persons.slice(-2)).join(' and ') 219 | } 220 | } 221 | 222 | function linkify_personnames(personnames) 223 | { 224 | for (var i = 0; i < personnames.length; i++) { 225 | personnames[i] = $('') 226 | .attr({ 227 | href: baseUrl+'?q='+encodeURIComponent(personnames[i]), 228 | title: 'Search for "'+personnames[i]+'"' 229 | }) 230 | .text(personnames[i]) 231 | .prop('outerHTML'); 232 | }; 233 | 234 | return personnames; 235 | } 236 | 237 | }); 238 | -------------------------------------------------------------------------------- /testdata.sql.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cccc/media-frontend/3e0ec0c10a169a4af1096392c1b3ec2942750a75/testdata.sql.gz --------------------------------------------------------------------------------