├── Procfile ├── public ├── favicon.png ├── mobdev.png ├── images │ ├── headerbg.jpg │ ├── arrow-down.png │ ├── logo-email.gif │ ├── mission-1.png │ ├── mission-2.png │ ├── mission-3.png │ ├── contact-mapbg.png │ ├── transparent.png │ ├── contact-mappin.png │ ├── mission-overlay.png │ ├── tmp-background.png │ ├── footerlinks-sprite.png │ ├── header-logo-mobile.png │ ├── header-menutoggle.png │ ├── jobs-plus-sprite.png │ ├── media-playbutton.png │ ├── team-plus-sprite.png │ ├── arrow-down-inverted.png │ ├── header-icons-sprite.png │ ├── media-navbuttons-sprite.png │ ├── logo-01.svg │ ├── arrow-down.svg │ ├── arrow-down-inverted.svg │ ├── ETH_DEV_LOGO.svg │ ├── ETH_DEV_LOGO_LARGE.svg │ ├── ETH_DEV_LOGO_SMALL.svg │ ├── logo.svg │ ├── jobs-plus-sprite.svg │ ├── team-plus-sprite.svg │ ├── header-logo-mobile.svg │ ├── media-navbuttons-sprite.svg │ └── media-playbutton.svg ├── videos │ ├── header_BG.mp4 │ ├── header_BG.ogv │ ├── header_BG.webm │ ├── mission-1.mp4 │ ├── mission-1.ogv │ ├── mission-1.webm │ ├── mission-2.mp4 │ ├── mission-2.ogv │ ├── mission-2.webm │ ├── mission-3.mp4 │ ├── mission-3.ogv │ ├── mission-3.webm │ ├── header_alpha.mov │ ├── header_logo.mov │ ├── header_BG_half.mp4 │ ├── header_BG_half.ogv │ ├── header_BG_half.webm │ ├── header_BG_orig.mp4 │ ├── ETH_DEV_ANIMATION_WEBSITE.mp4 │ └── ETH_DEV_ANIMATION_WEBSITE.webmsd.webm ├── fonts │ ├── Proxima Nova Reg.eot │ ├── Proxima Nova Reg.svg │ ├── Proxima Nova Reg.ttf │ ├── Proxima Nova Bold.eot │ ├── Proxima Nova Bold.svg │ ├── Proxima Nova Bold.ttf │ ├── Proxima Nova Bold.woff │ ├── Proxima Nova Light.eot │ ├── Proxima Nova Light.svg │ ├── Proxima Nova Light.ttf │ ├── Proxima Nova Light.woff │ ├── Proxima Nova Reg It.eot │ ├── Proxima Nova Reg It.svg │ ├── Proxima Nova Reg It.ttf │ ├── Proxima Nova Reg.woff │ ├── Proxima Nova Bold It.eot │ ├── Proxima Nova Bold It.svg │ ├── Proxima Nova Bold It.ttf │ ├── Proxima Nova Bold It.woff │ ├── Proxima Nova Light It.eot │ ├── Proxima Nova Light It.svg │ ├── Proxima Nova Light It.ttf │ ├── Proxima Nova Reg It.woff │ ├── Proxima Nova Light It.woff │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── static │ └── profileimages │ │ ├── .jpg │ │ ├── vitalik,.jpg │ │ ├── vitalik.jpg │ │ ├── 5431bd32787633abf1f3182b.jpg │ │ └── 5437f4bbd6f2a6ff24a7512d.jpg ├── styles │ ├── site │ │ ├── homepage.less │ │ ├── mixins.less │ │ ├── variables.less │ │ ├── typography.less │ │ ├── utils.less │ │ ├── sections │ │ │ ├── opener.less │ │ │ ├── contact.less │ │ │ ├── mission.less │ │ │ ├── team.less │ │ │ ├── jobs.less │ │ │ └── media.less │ │ ├── forms.less │ │ ├── layout.less │ │ └── header.less │ ├── site.less │ ├── fonts.css │ └── magnific-popup.css └── js │ ├── lib │ ├── masonry-horizontal.min.js │ ├── masonry-horizontal.js │ ├── packery-mode.pkgd.min.js │ └── jquery.magnific-popup.min.js │ └── site.js ├── templates ├── views │ ├── errors │ │ ├── 404.jade │ │ └── 500.jade │ ├── site │ │ ├── opener.jade │ │ ├── jobs.jade │ │ ├── team.jade │ │ ├── mission.jade │ │ ├── media.jade │ │ └── contact.jade │ ├── gallery.jade │ ├── post.jade │ ├── index.jade │ └── blog.jade ├── mixins │ ├── section_footer.jade │ └── flash-messages.jade └── layouts │ └── default.jade ├── .editorconfig ├── updates └── 0.0.1-admins.js ├── routes ├── views │ ├── gallery.js │ ├── post.js │ ├── contact.js │ ├── index.js │ └── blog.js ├── index.js └── middleware.js ├── models ├── PostCategory.js ├── Gallery.js ├── Job.js ├── Profile.js ├── Link.js ├── User.js ├── File.js ├── Post.js ├── Video.js ├── location.js ├── Enquiry.js └── mission.js ├── newrelic.js ├── package.json ├── .gitignore ├── gulpfile.js ├── .jshintrc └── keystone.js /Procfile: -------------------------------------------------------------------------------- 1 | web: node keystone.js 2 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/favicon.png -------------------------------------------------------------------------------- /public/mobdev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/mobdev.png -------------------------------------------------------------------------------- /public/images/headerbg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/headerbg.jpg -------------------------------------------------------------------------------- /public/images/arrow-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/arrow-down.png -------------------------------------------------------------------------------- /public/images/logo-email.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/logo-email.gif -------------------------------------------------------------------------------- /public/images/mission-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/mission-1.png -------------------------------------------------------------------------------- /public/images/mission-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/mission-2.png -------------------------------------------------------------------------------- /public/images/mission-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/mission-3.png -------------------------------------------------------------------------------- /public/videos/header_BG.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_BG.mp4 -------------------------------------------------------------------------------- /public/videos/header_BG.ogv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_BG.ogv -------------------------------------------------------------------------------- /public/videos/header_BG.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_BG.webm -------------------------------------------------------------------------------- /public/videos/mission-1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-1.mp4 -------------------------------------------------------------------------------- /public/videos/mission-1.ogv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-1.ogv -------------------------------------------------------------------------------- /public/videos/mission-1.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-1.webm -------------------------------------------------------------------------------- /public/videos/mission-2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-2.mp4 -------------------------------------------------------------------------------- /public/videos/mission-2.ogv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-2.ogv -------------------------------------------------------------------------------- /public/videos/mission-2.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-2.webm -------------------------------------------------------------------------------- /public/videos/mission-3.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-3.mp4 -------------------------------------------------------------------------------- /public/videos/mission-3.ogv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-3.ogv -------------------------------------------------------------------------------- /public/videos/mission-3.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/mission-3.webm -------------------------------------------------------------------------------- /public/images/contact-mapbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/contact-mapbg.png -------------------------------------------------------------------------------- /public/images/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/transparent.png -------------------------------------------------------------------------------- /public/videos/header_alpha.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_alpha.mov -------------------------------------------------------------------------------- /public/videos/header_logo.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_logo.mov -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Reg.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Reg.eot -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Reg.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Reg.svg -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Reg.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Reg.ttf -------------------------------------------------------------------------------- /public/images/contact-mappin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/contact-mappin.png -------------------------------------------------------------------------------- /public/images/mission-overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/mission-overlay.png -------------------------------------------------------------------------------- /public/images/tmp-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/tmp-background.png -------------------------------------------------------------------------------- /public/static/profileimages/.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/static/profileimages/.jpg -------------------------------------------------------------------------------- /public/videos/header_BG_half.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_BG_half.mp4 -------------------------------------------------------------------------------- /public/videos/header_BG_half.ogv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_BG_half.ogv -------------------------------------------------------------------------------- /public/videos/header_BG_half.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_BG_half.webm -------------------------------------------------------------------------------- /public/videos/header_BG_orig.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/header_BG_orig.mp4 -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Bold.eot -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Bold.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Bold.svg -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Bold.ttf -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Bold.woff -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Light.eot -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Light.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Light.svg -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Light.ttf -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Light.woff -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Reg It.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Reg It.eot -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Reg It.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Reg It.svg -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Reg It.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Reg It.ttf -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Reg.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Reg.woff -------------------------------------------------------------------------------- /public/images/footerlinks-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/footerlinks-sprite.png -------------------------------------------------------------------------------- /public/images/header-logo-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/header-logo-mobile.png -------------------------------------------------------------------------------- /public/images/header-menutoggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/header-menutoggle.png -------------------------------------------------------------------------------- /public/images/jobs-plus-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/jobs-plus-sprite.png -------------------------------------------------------------------------------- /public/images/media-playbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/media-playbutton.png -------------------------------------------------------------------------------- /public/images/team-plus-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/team-plus-sprite.png -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Bold It.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Bold It.eot -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Bold It.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Bold It.svg -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Bold It.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Bold It.ttf -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Bold It.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Bold It.woff -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Light It.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Light It.eot -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Light It.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Light It.svg -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Light It.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Light It.ttf -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Reg It.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Reg It.woff -------------------------------------------------------------------------------- /public/images/arrow-down-inverted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/arrow-down-inverted.png -------------------------------------------------------------------------------- /public/images/header-icons-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/header-icons-sprite.png -------------------------------------------------------------------------------- /public/fonts/Proxima Nova Light It.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/Proxima Nova Light It.woff -------------------------------------------------------------------------------- /public/images/media-navbuttons-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/images/media-navbuttons-sprite.png -------------------------------------------------------------------------------- /public/static/profileimages/vitalik,.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/static/profileimages/vitalik,.jpg -------------------------------------------------------------------------------- /public/static/profileimages/vitalik.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/static/profileimages/vitalik.jpg -------------------------------------------------------------------------------- /public/videos/ETH_DEV_ANIMATION_WEBSITE.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/ETH_DEV_ANIMATION_WEBSITE.mp4 -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public/videos/ETH_DEV_ANIMATION_WEBSITE.webmsd.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/videos/ETH_DEV_ANIMATION_WEBSITE.webmsd.webm -------------------------------------------------------------------------------- /public/static/profileimages/5431bd32787633abf1f3182b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/static/profileimages/5431bd32787633abf1f3182b.jpg -------------------------------------------------------------------------------- /public/static/profileimages/5437f4bbd6f2a6ff24a7512d.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethereum/ethdev-site/HEAD/public/static/profileimages/5437f4bbd6f2a6ff24a7512d.jpg -------------------------------------------------------------------------------- /templates/views/errors/404.jade: -------------------------------------------------------------------------------- 1 | extends ../../layouts/default 2 | 3 | block content 4 | .container 5 | h1 404 6 | p.lead Sorry, the page you requested can't be found. -------------------------------------------------------------------------------- /templates/views/errors/500.jade: -------------------------------------------------------------------------------- 1 | extends ../../layouts/default 2 | 3 | block content 4 | .container 5 | h1 Error (500) 6 | p.lead Sorry, the site has encountered an error. -------------------------------------------------------------------------------- /templates/mixins/section_footer.jade: -------------------------------------------------------------------------------- 1 | mixin section_footer(color, inverse) 2 | - var inverse = inverse || false; 3 | .section-footer 4 | if(color) 5 | div(class="tab sr-only #{inverse ? 'inverted' : ''}", style="background-color:#{color}") 6 | else 7 | .tab.sr-only 8 | Next section 9 | 10 | -------------------------------------------------------------------------------- /public/styles/site/homepage.less: -------------------------------------------------------------------------------- 1 | #homepage { 2 | #opener { 3 | background-color:white; 4 | } 5 | @import "./sections/opener.less"; 6 | @import "./sections/mission.less"; 7 | @import "./sections/media.less"; 8 | @import "./sections/team.less"; 9 | @import "./sections/jobs.less"; 10 | @import "./sections/contact.less"; 11 | } 12 | -------------------------------------------------------------------------------- /templates/views/site/opener.jade: -------------------------------------------------------------------------------- 1 | section#opener 2 | .video-container 3 | video(autoplay, muted, preload, autobuffer, poster="/images/ETH_DEV_LOGO_LARGE.svg") 4 | source(src="/videos/ETH_DEV_ANIMATION_WEBSITE.mp4", type="video/mp4") 5 | source(src="/videos/ETH_DEV_ANIMATION_WEBSITE.webmsd.webm", type="video/webm") 6 | +section_footer() 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = false 9 | insert_final_newline = true 10 | indent_style = tab 11 | 12 | [{*.yml,*.json}] 13 | indent_style = space 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /updates/0.0.1-admins.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This script automatically creates a default Admin user when an 3 | * empty database is used for the first time. You can use this 4 | * technique to insert data into any List you have defined. 5 | */ 6 | 7 | exports.create = { 8 | User: [ 9 | { 'name.first': 'Admin', 'name.last': 'User', email: 'admin@example.com', password: 'admin', isAdmin: true } 10 | ] 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /public/styles/site.less: -------------------------------------------------------------------------------- 1 | @import "../../node_modules/bootstrap/less/normalize.less"; 2 | 3 | @import "./magnific-popup.css"; 4 | 5 | @import "site/variables.less"; 6 | @import "site/mixins.less"; 7 | 8 | @import "site/utils.less"; 9 | 10 | @import "site/typography.less"; 11 | @import "site/layout.less"; 12 | 13 | @import "site/forms.less"; 14 | 15 | @import "site/header.less"; 16 | @import "site/homepage.less"; 17 | -------------------------------------------------------------------------------- /routes/views/gallery.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'); 2 | 3 | exports = module.exports = function(req, res) { 4 | 5 | var view = new keystone.View(req, res), 6 | locals = res.locals; 7 | 8 | // Set locals 9 | locals.section = 'gallery'; 10 | 11 | // Load the galleries by sortOrder 12 | view.query('galleries', keystone.list('Gallery').model.find({}).sort('sortOrder')); 13 | 14 | // Render the view 15 | view.render('gallery'); 16 | 17 | }; 18 | -------------------------------------------------------------------------------- /public/styles/site/mixins.less: -------------------------------------------------------------------------------- 1 | .ir() { 2 | text-indent: 200%; 3 | white-space: nowrap; 4 | overflow: hidden; 5 | } 6 | 7 | .clearfix() { 8 | &:before, 9 | &:after { 10 | content: " "; /* 1 */ 11 | display: table; /* 2 */ 12 | } 13 | 14 | &:after { 15 | clear: both; 16 | } 17 | 18 | /** 19 | * For IE 6/7 only 20 | * Include this rule to trigger hasLayout and contain floats. 21 | */ 22 | & { 23 | *zoom: 1; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /models/PostCategory.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types; 3 | 4 | /** 5 | * PostCategory Model 6 | * ================== 7 | */ 8 | 9 | var PostCategory = new keystone.List('PostCategory', { 10 | autokey: { from: 'name', path: 'key', unique: true } 11 | }); 12 | 13 | PostCategory.add({ 14 | name: { type: String, required: true } 15 | }); 16 | 17 | PostCategory.relationship({ ref: 'Post', path: 'categories' }); 18 | 19 | PostCategory.register(); 20 | -------------------------------------------------------------------------------- /models/Gallery.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types; 3 | 4 | /** 5 | * Gallery Model 6 | * ============= 7 | */ 8 | 9 | var Gallery = new keystone.List('Gallery', { 10 | autokey: { from: 'name', path: 'key', unique: true } 11 | }); 12 | 13 | Gallery.add({ 14 | name: { type: String, required: true }, 15 | publishedDate: { type: Date, default: Date.now }, 16 | heroImage: { type: Types.CloudinaryImage }, 17 | images: { type: Types.CloudinaryImages } 18 | }); 19 | 20 | Gallery.register(); 21 | -------------------------------------------------------------------------------- /models/Job.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types; 3 | 4 | var Job = new keystone.List('Job', { 5 | autokey: { from: 'title', path: 'key', unique: true }, 6 | map: { name: 'title' }, 7 | defaultSort: '+editedDate' 8 | }); 9 | 10 | Job.add({ 11 | title: { type: String, required: true, initial: true }, 12 | description: { type: Types.Markdown }, 13 | publishedDate: { type: Date, default: function() { return Date.now() }, hidden: true }, 14 | editedDate: { type: Date, default: function() { return Date.now() } }, 15 | skills: { type: String } 16 | }); 17 | 18 | Job.register(); 19 | 20 | -------------------------------------------------------------------------------- /models/Profile.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | path = require('path'), 3 | Types = keystone.Field.Types; 4 | 5 | var Profile = new keystone.List('Profile', { 6 | sortable: true 7 | }), 8 | filePrefix = '/static/profileimages'; 9 | 10 | Profile.add({ 11 | firstname: { type: Types.Text, required: true, initial: true }, 12 | lastname: { type: Types.Text }, 13 | biography: { type: Types.Markdown }, 14 | photo: { 15 | type: Types.CloudinaryImage, 16 | width: 300, 17 | height: 300, 18 | thumbnail: '300, 300' 19 | } 20 | }); 21 | 22 | Profile.defaultColumns = 'firstname, lastname'; 23 | 24 | Profile.register(); 25 | -------------------------------------------------------------------------------- /templates/views/site/jobs.jade: -------------------------------------------------------------------------------- 1 | section#jobs 2 | .container 3 | h2 Job Offers 4 | 5 | ul.job-offers 6 | each job, index in jobsSectionList 7 | +job_offer(job, index) 8 | 9 | +section_footer("#4d4d4d", true) 10 | 11 | mixin job_offer(job, index) 12 | - var skills = job.skills ? job.skills.split('|') : []; 13 | - var alternate = index % 2 ? "alternate" : ""; 14 | li(class="job-offer #{alternate}") 15 | h3.title= job.title 16 | .date= job._.editedDate.format('MMM YYYY') 17 | .description 18 | | !{job.description.html} 19 | if skills 20 | ul 21 | each skill in skills 22 | li= skill 23 | button.btn.btn-primary.apply Apply for role 24 | 25 | -------------------------------------------------------------------------------- /models/Link.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types; 3 | 4 | var Link = new keystone.List('Link', { 5 | autokey: { from: 'title', path: 'key', unique: true }, 6 | map: { name: 'title' }, 7 | defaultSort: '+editedDate' 8 | }); 9 | 10 | Link.add({ 11 | title: { type: String, required: true, initial: true }, 12 | description: { type: String }, 13 | publishedDate: { type: Date, default: function() { return Date.now() }, hidden: true }, 14 | editedDate: { type: Date, default: function() { return Date.now() } }, 15 | heroImage: { 16 | type: Types.CloudinaryImage 17 | }, 18 | url: { type: Types.Url, required: true, initial: true } 19 | }); 20 | 21 | Link.register(); 22 | 23 | -------------------------------------------------------------------------------- /newrelic.js: -------------------------------------------------------------------------------- 1 | /** 2 | * New Relic agent configuration. 3 | * 4 | * See lib/config.defaults.js in the agent distribution for a more complete 5 | * description of configuration variables and their potential values. 6 | */ 7 | exports.config = { 8 | /** 9 | * Array of application names. 10 | */ 11 | app_name : ['ethdev'], 12 | /** 13 | * Your New Relic license key. 14 | */ 15 | license_key : process.env.NEWRELIC_LICENSE_KEY, 16 | logging : { 17 | /** 18 | * Level at which to log. 'trace' is most useful to New Relic when diagnosing 19 | * issues with the agent, 'info' and higher will impose the least overhead on 20 | * production applications. 21 | */ 22 | level : 'info' 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ethereumdev", 3 | "version": "0.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "async": "~0.9.0", 7 | "autoprefixer": "^3.1.0", 8 | "bootstrap": "^3.2.0", 9 | "dotenv": "0.4.0", 10 | "keystone": "^0.2.30", 11 | "marked": "^0.3.2", 12 | "moment": "^2.8.3", 13 | "underscore": "~1.7.0", 14 | "newrelic": "^1.14.1", 15 | "mailgun-js": "0.6.7" 16 | }, 17 | "devDependencies": { 18 | "gulp": "~3.6.2", 19 | "gulp-jshint": "~1.6.1", 20 | "jshint-stylish": "~0.1.3", 21 | "gulp-watch": "~0.6.5" 22 | }, 23 | "engines": { 24 | "node": ">=0.10.22", 25 | "npm": ">=1.3.14" 26 | }, 27 | "scripts": { 28 | "start": "node keystone.js" 29 | }, 30 | "main": "keystone.js" 31 | } 32 | -------------------------------------------------------------------------------- /templates/mixins/flash-messages.jade: -------------------------------------------------------------------------------- 1 | mixin flash-messages(messages) 2 | if messages 3 | #flash-messages.container 4 | each message in messages.info 5 | +flash-message(message, 'info') 6 | each message in messages.success 7 | +flash-message(message, 'success') 8 | each message in messages.warning 9 | +flash-message(message, 'warning') 10 | each message in messages.error 11 | +flash-message(message, 'danger') 12 | 13 | mixin flash-message(message, type) 14 | div(class='alert alert-' + type) 15 | if utils.isObject(message) 16 | if message.title 17 | h4= message.title 18 | if message.detail 19 | p= message.detail 20 | if message.list 21 | ul 22 | each item in message.list 23 | li= item 24 | else 25 | = message -------------------------------------------------------------------------------- /public/styles/site/variables.less: -------------------------------------------------------------------------------- 1 | // Override Bootstrap variables in this file, e.g. 2 | 3 | @media-desktop: 768pt; 4 | 5 | @proxima: "Proxima Nova Reg"; 6 | @proxima-italic: "Proxima Nova Reg It"; 7 | @proxima-light: "Proxima Nova Light"; 8 | @proxima-light-italic: "Proxima Nova Light It"; 9 | @proxima-bold: "Proxima Nova Bold"; 10 | @proxima-bold-italic: "Proxima Nova Bold It"; 11 | 12 | @font-size-base: 14pt; 13 | @font-size-ratio-desktop: 0.85; 14 | 15 | @font-line-height-base: 18pt; 16 | 17 | @font-family-global: @proxima-light, Helvetica, Arial, sans-serif; 18 | 19 | @gray-dark: #4d4d4d; 20 | @gray: #656565; 21 | @gray-light: #BBB; 22 | @gray-lighter: #f0f0f0; 23 | 24 | @blue-lighter: #c9e9f6; 25 | @blue-light: #78c7e8; 26 | 27 | @page-header-height: 36pt; 28 | 29 | @mobile-padding: 1em; 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Compiled binary addons (http://nodejs.org/api/addons.html) 17 | build/Release 18 | 19 | # Dependency directory 20 | # Deployed apps should consider commenting this line out: 21 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 22 | node_modules 23 | 24 | # Ignore .env configuration files 25 | .env 26 | 27 | # Ignore .DS_Store files on OS X 28 | .DS_Store 29 | public/files/ 30 | 31 | ethdev.json 32 | deploy.json 33 | 34 | public/styles/*.min.css 35 | 36 | #Ignore Jetbrains project config 37 | .idea/ 38 | 39 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | jshint = require('gulp-jshint'), 3 | jshintReporter = require('jshint-stylish'), 4 | watch = require('gulp-watch'); 5 | 6 | /* 7 | * Create variables for our project paths so we can change in one place 8 | */ 9 | var paths = { 10 | 'src':['./models/**/*.js','./routes/**/*.js', 'keystone.js', 'package.json'], 11 | // enable for tests 12 | //'tests':['./test/*.js', './test/**/*.js'] 13 | }; 14 | 15 | 16 | // gulp lint 17 | gulp.task('lint', function(){ 18 | gulp.src(paths.src) 19 | .pipe(jshint()) 20 | .pipe(jshint.reporter(jshintReporter)); 21 | 22 | }); 23 | 24 | // gulp watcher for lint 25 | gulp.task('watchLint', function () { 26 | gulp.src(paths.src) 27 | .pipe(watch()) 28 | .pipe(jshint()) 29 | .pipe(jshint.reporter(jshintReporter)); 30 | }); 31 | -------------------------------------------------------------------------------- /templates/views/gallery.jade: -------------------------------------------------------------------------------- 1 | extends ../layouts/default 2 | 3 | block intro 4 | .container 5 | h1 Gallery 6 | 7 | block content 8 | .container 9 | if galleries.length 10 | each gallery in galleries 11 | h2= gallery.name 12 | if gallery.publishedDate 13 | .pull-right.text-muted= gallery._.publishedDate.format('Do MMM YYYY') 14 | 15 | .row.gallery-images 16 | if gallery.heroImage.exists 17 | .col-sm-4.col-md-4.gallery-image: img(src=gallery._.heroImage.limit(680,680)).img-rounded 18 | .col-sm-8.col-md-8: .row 19 | each image in gallery.images 20 | .col-xs-4.col-sm-4.col-md-3.gallery-image: img(src=image.limit(300,300)).img-rounded 21 | else 22 | each image in gallery.images 23 | .col-xs-6.col-sm-4.col-md-3.gallery-image: img(src=image.limit(300,300)).img-rounded 24 | else 25 | h3.text-muted There are no image galleries yet. 26 | -------------------------------------------------------------------------------- /templates/views/site/team.jade: -------------------------------------------------------------------------------- 1 | section#team 2 | .container 3 | h2 Team 4 | 5 | .lead-profile.hidden 6 | - var dummyProfile = { photo:{path:'', filename:''}, firstname:'', lastname:'', biography:{md:'', html:''} } 7 | +team_profile(dummyProfile) 8 | 9 | .team-profiles 10 | each profile, index in teamSectionProfiles 11 | +team_profile(profile, index) 12 | 13 | +section_footer("#f0f0f0") 14 | 15 | mixin team_profile(profile, index) 16 | - var largeClass = index < 3 ? "large" : "" 17 | div(class="profile #{largeClass}") 18 | .photo 19 | //-- var photoUrl = profile.photo.path + "/" + profile.photo.filename; 20 | //-- photoUrl = photoUrl.replace('public/', '') 21 | img(src=profile.photo.secure_url) 22 | h3.name 23 | .firstname #{profile.firstname} 24 | .lastname #{profile.lastname} 25 | if profile.biography 26 | .bio-copy!= profile.biography.html 27 | -------------------------------------------------------------------------------- /templates/views/post.jade: -------------------------------------------------------------------------------- 1 | extends ../layouts/default 2 | 3 | block content 4 | .container: .row: .col-sm-10.col-sm-offset-1.col-md-8.col-md-offset-2 5 | article 6 | p: a(href='/blog') ← back to the blog 7 | hr 8 | if !data.post 9 | h2 Invalid Post. 10 | else 11 | header 12 | h1= data.post.title 13 | h5 Posted 14 | if data.post.publishedDate 15 | | on #{data.post._.publishedDate.format('MMMM Do, YYYY')} 16 | if data.post.categories && data.post.categories.length 17 | | in 18 | each cat, cat_i in data.post.categories 19 | a(href='/blog/' + cat.key)= cat.name 20 | if cat_i < data.post.categories.length - 1 21 | | , 22 | else 23 | | 24 | if data.post.author 25 | | by #{data.post.author.name.first} 26 | .post 27 | if data.post.image.exists 28 | .image-wrap: img(src=data.post._.image.fit(750,450)).img-responsive 29 | != data.post.content.full 30 | -------------------------------------------------------------------------------- /models/User.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types; 3 | 4 | /** 5 | * User Model 6 | * ========== 7 | */ 8 | 9 | var User = new keystone.List('User'); 10 | 11 | User.add({ 12 | name: { type: Types.Name, required: true, index: true }, 13 | email: { type: Types.Email, initial: true, required: true, index: true }, 14 | password: { type: Types.Password, initial: true, required: true }, 15 | receiveEnquiries: {type: Boolean, label: 'Receives enquiries by email', index: true} 16 | }, 'Permissions', { 17 | isAdmin: { type: Boolean, label: 'Can access Keystone', index: true } 18 | }); 19 | 20 | // Provide access to Keystone 21 | User.schema.virtual('canAccessKeystone').get(function() { 22 | return this.isAdmin; 23 | }); 24 | 25 | 26 | /** 27 | * Relationships 28 | */ 29 | 30 | User.relationship({ ref: 'Post', path: 'author' }); 31 | 32 | 33 | /** 34 | * Registration 35 | */ 36 | 37 | User.defaultColumns = 'name, email, isAdmin'; 38 | User.register(); 39 | -------------------------------------------------------------------------------- /models/File.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | path = require('path'), 3 | Types = keystone.Field.Types; 4 | 5 | var File = new keystone.List('File', { 6 | autokey: { from: 'title', path: 'key', unique: true }, 7 | map: { name: 'title' }, 8 | defaultSort: '+editedDate' 9 | }); 10 | 11 | File.add({ 12 | title: { type: String, required: true, initial: true }, 13 | description: { type: String }, 14 | publishedDate: { type: Date, default: function() { return Date.now() }, hidden: true }, 15 | editedDate: { type: Date, default: function() { return Date.now() } }, 16 | icon: { 17 | type: Types.CloudinaryImage, 18 | width: 200, 19 | height: 200 20 | }, 21 | file: { 22 | type: Types.LocalFile, 23 | required: true, 24 | initial: false, 25 | dest: path.join(global.APP_ROOT, 'public/files'), 26 | prefix: '/files', 27 | filename: function(doc, file) { 28 | return file.replace(/[#@\s]/g, ''); 29 | }, 30 | } 31 | }); 32 | 33 | File.register(); 34 | -------------------------------------------------------------------------------- /public/styles/site/typography.less: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | body { 6 | font-family: @font-family-global; 7 | font-size: @font-size-base; 8 | line-height: @font-line-height-base; 9 | transition: font-size .6s ease-in-out; 10 | color: @gray-dark; 11 | } 12 | 13 | a { 14 | &, &:link, &:visited, &:hover { 15 | color: @blue-light; 16 | text-decoration:none; 17 | } 18 | } 19 | 20 | h1, h2, h3, h4, h5, h6, b, strong { 21 | font-weight:normal; 22 | font-family: @proxima; 23 | } 24 | 25 | i, em { 26 | font-style:normal; 27 | font-family: @proxima-light-italic; 28 | } 29 | 30 | h1 { 31 | font-size: @font-size-base * 1.875; 32 | font-family: @font-family-global; 33 | } 34 | 35 | h2 { 36 | font-size: @font-size-base * 1.7; 37 | text-align: center; 38 | text-transform: uppercase; 39 | line-height: 1.3em; 40 | } 41 | 42 | @media all and (min-width: @media-desktop) { 43 | body { 44 | font-size: @font-size-base * @font-size-ratio-desktop; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /models/Post.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types; 3 | 4 | /** 5 | * Post Model 6 | * ========== 7 | */ 8 | 9 | var Post = new keystone.List('Post', { 10 | map: { name: 'title' }, 11 | autokey: { path: 'slug', from: 'title', unique: true } 12 | }); 13 | 14 | Post.add({ 15 | title: { type: String, required: true }, 16 | state: { type: Types.Select, options: 'draft, published, archived', default: 'draft', index: true }, 17 | author: { type: Types.Relationship, ref: 'User', index: true }, 18 | publishedDate: { type: Types.Date, index: true, dependsOn: { state: 'published' } }, 19 | image: { type: Types.CloudinaryImage }, 20 | content: { 21 | brief: { type: Types.Html, wysiwyg: true, height: 150 }, 22 | extended: { type: Types.Html, wysiwyg: true, height: 400 } 23 | }, 24 | categories: { type: Types.Relationship, ref: 'PostCategory', many: true } 25 | }); 26 | 27 | Post.schema.virtual('content.full').get(function() { 28 | return this.content.extended || this.content.brief; 29 | }); 30 | 31 | Post.defaultColumns = 'title, state|20%, author|20%, publishedDate|20%'; 32 | Post.register(); 33 | -------------------------------------------------------------------------------- /templates/views/index.jade: -------------------------------------------------------------------------------- 1 | extends ../layouts/default 2 | 3 | block content 4 | include ./site/opener 5 | - with(missionSection) 6 | include ./site/mission 7 | 8 | - with(mediaSection) 9 | include ./site/media 10 | 11 | include ./site/team 12 | 13 | - with(jobsSection) 14 | include ./site/jobs 15 | 16 | - with(contactSection) 17 | include ./site/contact 18 | 19 | block footer 20 | a.footer-link.facebook(href="https://www.facebook.com/ethereumproject") Facebook 21 | a.footer-link.twitter(href="https://twitter.com/ethereumproject") Twitter 22 | a.footer-link.youtube(href="https://www.youtube.com/user/ethereumproject") Youtube 23 | a.footer-link.reddit(href="http://www.reddit.com/r/ethereum/") Reddit 24 | a.footer-link.forum(href="https://forum.ethereum.org/") Forum 25 | a.footer-link.irc(href="https://webchat.freenode.net/?channels=%23ethereum") Chat 26 | a.footer-link.linkedin(href="https://www.linkedin.com/company/5091692") Linkedin 27 | a.footer-link.github(href="https://github.com/ethereum") Github 28 | 29 | p.copyright All content copyright © Eth Dev Ltd. All rights reserved. 30 | -------------------------------------------------------------------------------- /models/Video.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types; 3 | 4 | var Video = new keystone.List('Video', { 5 | autokey: { from: 'title', path: 'key', unique: true }, 6 | map: { name: 'title' }, 7 | defaultSort: '-publishedDate' 8 | }); 9 | 10 | Video.add({ 11 | title: { type: String, required: true, initial: true }, 12 | description: { type: String }, 13 | publishedDate: { type: Date, default: function() { return Date.now() }, hidden: true }, 14 | editedDate: { type: Date, default: function() { return Date.now() } }, 15 | heroImage: { 16 | type: Types.CloudinaryImage, 17 | width: 600, 18 | height: 600, 19 | thumbnail: '600, 600' 20 | }, 21 | videoId: { 22 | type: String, 23 | required: true, 24 | initial: true, 25 | note: 'Youtube URL (eg. \'https://www.youtube.com/watch?v=o6D8Up411dI\')', 26 | watch: true, 27 | value: function() { 28 | var match = this.videoId.match(/v=([^&]+)/); 29 | return match && match[1] ? 30 | this.videoId.match(/v=([^&]+)/)[1] : 31 | this.videoId || ''; 32 | } 33 | } 34 | }); 35 | 36 | Video.register(); 37 | 38 | -------------------------------------------------------------------------------- /routes/views/post.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | async = require('async'); 3 | 4 | exports = module.exports = function(req, res) { 5 | 6 | var view = new keystone.View(req, res), 7 | locals = res.locals; 8 | 9 | // Set locals 10 | locals.section = 'blog'; 11 | locals.filters = { 12 | post: req.params.post 13 | }; 14 | locals.data = { 15 | posts: [] 16 | }; 17 | 18 | // Load the current post 19 | view.on('init', function(next) { 20 | 21 | var q = keystone.list('Post').model.findOne({ 22 | state: 'published', 23 | slug: locals.filters.post 24 | }).populate('author categories'); 25 | 26 | q.exec(function(err, result) { 27 | locals.data.post = result; 28 | next(err); 29 | }); 30 | 31 | }); 32 | 33 | // Load other posts 34 | view.on('init', function(next) { 35 | 36 | var q = keystone.list('Post').model.find().where('state', 'published').sort('-publishedDate').populate('author').limit('4'); 37 | 38 | q.exec(function(err, results) { 39 | locals.data.posts = results; 40 | next(err); 41 | }); 42 | 43 | }); 44 | 45 | // Render the view 46 | view.render('post'); 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /templates/views/site/mission.jade: -------------------------------------------------------------------------------- 1 | section#mission 2 | .container.mission-statement 3 | h2.statementTitle!= missionSectionMain[0].title 4 | .collapsible-statement 5 | .lead!= missionSectionMain[0].description.html 6 | br 7 | .toggle-wrapper 8 | .toggle-container 9 | 10 | +mission_objectives(missionSectionObjectives) 11 | 12 | +section_footer("#f0f0f0") 13 | 14 | mixin mission_objectives(objectives) 15 | ol.mission-steps 16 | each objective, index in objectives 17 | +mission_objective(objective, index) 18 | - if(index === 3) return; 19 | 20 | mixin mission_objective(o, i) 21 | li.step 22 | h3= o.title 23 | if missionSection.images[i] 24 | .video-container 25 | video(autoplay, poster="/images/transparent.png", style="background-image:url('/images/#{missionSection.images[i]}.png')") 26 | source(src="/videos/#{missionSection.images[i]}.ogv", type="video/ogg") 27 | source(src="/videos/#{missionSection.images[i]}.mp4", type="video/mp4") 28 | source(src="/videos/#{missionSection.images[i]}.webm", type="video/webm") 29 | div.info!= o.description.html 30 | 31 | -------------------------------------------------------------------------------- /public/styles/site/utils.less: -------------------------------------------------------------------------------- 1 | @footer-height: 78px; 2 | 3 | .section-footer { 4 | overflow: hidden; 5 | position: relative; 6 | bottom: @footer-height * -0.5; 7 | cursor: pointer; 8 | 9 | .tab { 10 | .ir(); 11 | width: @footer-height; 12 | height: @footer-height; 13 | margin-top: @footer-height * -0.5; 14 | margin-left: auto; 15 | margin-right: auto; 16 | background-color: white; 17 | background-image: url('/images/arrow-down.svg'); 18 | background-repeat: no-repeat; 19 | background-position: 50% 65%; 20 | background-size: 40%; 21 | border-radius: 0 0 50% 50%; 22 | 23 | &.inverted { 24 | background-image: url('/images/arrow-down-inverted.svg'); 25 | } 26 | } 27 | 28 | @media all and (min-width: @media-desktop) { 29 | /*bottom: (@footer-height * -1) - 28px;*/ 30 | } 31 | } 32 | 33 | .lead { 34 | width: 100%; 35 | margin:auto; 36 | text-align: center; 37 | padding: 0 10%; 38 | margin-bottom: 14%; 39 | 40 | @media all and (min-width: @media-desktop) { 41 | width: 75%; 42 | padding-left:12.5pt; 43 | padding-right:12.5pt; 44 | margin-bottom: 3em; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /public/styles/site/sections/opener.less: -------------------------------------------------------------------------------- 1 | #opener { 2 | padding-top:0; 3 | background-color: white; 4 | height: 400px; 5 | margin-top: 60px; 6 | position: relative; 7 | background-size: cover; 8 | background-position: 50% 50%; 9 | 10 | .container { 11 | height: 100%; 12 | } 13 | 14 | .section-footer { 15 | position: absolute; 16 | bottom: @footer-height * -0.5; 17 | width:100%; 18 | } 19 | 20 | /*&:before {*/ 21 | /*content: " ";*/ 22 | /*display: block;*/ 23 | /*padding-top: 100%;*/ 24 | /*}*/ 25 | 26 | .logo { 27 | z-index:200; 28 | position: relative; 29 | margin-left: auto; 30 | margin-right: auto; 31 | margin-top:-3em; 32 | img { 33 | width: 100%; 34 | display: none; 35 | } 36 | } 37 | 38 | .video-container { 39 | width: 100%; 40 | height: 100%; 41 | overflow: hidden; 42 | position: absolute; 43 | } 44 | 45 | video { 46 | margin-top: -118px; 47 | z-index:100; 48 | width: 100%; 49 | height: 160%; 50 | position: absolute; 51 | background-color: transparent; 52 | } 53 | 54 | @media all and (min-width: @media-desktop) { 55 | max-height: 600px; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /public/styles/site/forms.less: -------------------------------------------------------------------------------- 1 | .form { 2 | width: 100%; 3 | padding-left: @mobile-padding; 4 | padding-right: @mobile-padding; 5 | 6 | &, .form-group { 7 | .clearfix(); 8 | } 9 | 10 | .form-group { 11 | display: block; 12 | clear: both; 13 | 14 | .form-label { 15 | .ir(); 16 | display: block; 17 | height: 0; 18 | } 19 | 20 | .form-control { 21 | width: 100%; 22 | font-size: 14pt; 23 | background-color: @gray-dark; 24 | padding: .5em; 25 | border: 0; 26 | outline: none; 27 | color: @gray-lighter; 28 | display: block; 29 | } 30 | 31 | margin-bottom: @mobile-padding; 32 | } 33 | } 34 | 35 | a.btn, button.btn { 36 | font-size: 14pt!important; 37 | padding: .25em; 38 | width: 100%; 39 | margin-right: 2.5%; 40 | display: block; 41 | float: left; 42 | color: white; 43 | background-color: @gray-light; 44 | color: white; 45 | text-align: center; 46 | text-transform: uppercase; 47 | border: 0; 48 | 49 | & + &, &.btn-right { 50 | float: right; 51 | margin-right: 0; 52 | margin-left: 2.5%; 53 | } 54 | 55 | &.btn-primary { 56 | background-color: @blue-light; 57 | } 58 | 59 | @media all and (min-width: @media-desktop) { 60 | width: 47.5%; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /routes/views/contact.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Enquiry = keystone.list('Enquiry'); 3 | 4 | exports = module.exports = function(req, res) { 5 | 6 | var view = new keystone.View(req, res), 7 | locals = res.locals; 8 | 9 | // Set locals 10 | locals.section = 'contact'; 11 | locals.enquiryTypes = Enquiry.fields.enquiryType.ops; 12 | locals.formData = req.body || {}; 13 | locals.validationErrors = {}; 14 | locals.enquirySubmitted = false; 15 | 16 | // On POST requests, add the Enquiry item to the database 17 | view.on('post', { action: 'contact' }, function(next) { 18 | 19 | var newEnquiry = new Enquiry.model(), 20 | updater = newEnquiry.getUpdateHandler(req); 21 | 22 | updater.process(req.body, { 23 | flashErrors: true, 24 | fields: 'name, email, enquiryType, message', 25 | errorMessage: 'There was a problem submitting your enquiry:' 26 | }, function(err) { 27 | if (err) { 28 | locals.validationErrors = err.errors; 29 | } else { 30 | locals.enquirySubmitted = true; 31 | } 32 | next(); 33 | }); 34 | 35 | }); 36 | 37 | view.render(function(err) { 38 | if (err) return res.apiError('error', err); 39 | 40 | res.apiResponse({ 41 | success: true 42 | }); 43 | }); 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /models/location.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types, 3 | async = require('async'); 4 | 5 | var Location = new keystone.List('Location', { 6 | autokey: { from: 'title', path: 'key', unique: true }, 7 | map: { name: 'title' }, 8 | defaultSort: '-publishedDate', 9 | sortable: true 10 | }); 11 | 12 | Location.add({ 13 | title: { type: String, required: true, initial: true }, 14 | coordinates: { type: Types.Location, required: true, initial: true }, 15 | telephone: { type: String }, 16 | email: { type: String }, 17 | publishedDate: { type: Date, default: function() { return Date.now() }, hidden: true }, 18 | editedDate: { type: Date, default: function() { return Date.now() }, hidden: true } 19 | }); 20 | 21 | Location.register(); 22 | 23 | Location.model.find().count(function(err, count) { 24 | if (count > 0) return; 25 | 26 | console.log('Seeding locations') 27 | async.series([ 28 | function(done) { 29 | var msg0 = (new Location.model({ 30 | "title": "DEV London", 31 | "address": "123 Somestreet\nLondon\nUnited Kingdom\nEC2A 1XY", 32 | "telephone": "+44 891 50 50 50", 33 | "email": "london@dev" 34 | })) 35 | msg0.save(function(err) { 36 | done(err) 37 | }) 38 | } 39 | ], function() {}); 40 | }) 41 | -------------------------------------------------------------------------------- /public/images/logo-01.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "camelcase": true, 4 | "curly": false, /* custom */ 5 | "eqeqeq": true, 6 | "es3": true, 7 | "forin": true, 8 | "freeze": true, 9 | "immed": true, 10 | "indent": 1, /* custom */ 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "noempty": true, 15 | "nonbsp": true, 16 | "nonew": true, 17 | "plusplus": false, /* custom */ 18 | "quotmark": true, 19 | "undef": true, 20 | "unused": true, 21 | "strict": false, /* enable later */ 22 | "trailing": true, 23 | "maxparams": false, 24 | "maxdepth": false, 25 | "maxstatements": false, 26 | "maxcomplexity": false, 27 | "maxlen": false, 28 | "asi": false, 29 | "boss": true, /* custom */ 30 | "debug": false, 31 | "eqnull": true, /* custom */ 32 | "esnext": false, 33 | "evil": false, 34 | "expr": false, 35 | "funcscope": false, 36 | "gcl": false, 37 | "globalstrict": false, 38 | "iterator": false, 39 | "lastsemic": false, 40 | "laxbreak": false, 41 | "laxcomma": false, 42 | "loopfunc": false, 43 | "moz": false, 44 | "multistr": false, 45 | "notypeof": false, 46 | "proto": false, 47 | "scripturl": false, 48 | "smarttabs": false, 49 | "shadow": false, 50 | "sub": false, 51 | "supernew": false, 52 | "noyield": false, 53 | "browser": true, /* custom */ 54 | "node": true, /* custom */ 55 | "onevar": true, /* custom */ 56 | "globals": { /* custom */ 57 | /* MOCHA: http://stackoverflow.com/a/19572515/130638 */ 58 | "describe" : false, 59 | "it" : false, 60 | "before" : false, 61 | "beforeEach" : false, 62 | "after" : false, 63 | "afterEach" : false 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /public/images/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 18 | 19 | 21 | 22 | -------------------------------------------------------------------------------- /public/images/arrow-down-inverted.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 18 | 19 | 21 | 22 | -------------------------------------------------------------------------------- /public/images/ETH_DEV_LOGO.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 17 | 19 | 21 | 22 | -------------------------------------------------------------------------------- /public/images/ETH_DEV_LOGO_LARGE.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 17 | 19 | 21 | 22 | -------------------------------------------------------------------------------- /public/images/ETH_DEV_LOGO_SMALL.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 17 | 19 | 21 | 22 | -------------------------------------------------------------------------------- /public/styles/site/sections/contact.less: -------------------------------------------------------------------------------- 1 | #contact { 2 | .clearfix(); 3 | background-color: @gray-lighter; 4 | border-bottom: 0; 5 | 6 | .map { 7 | display: none; 8 | } 9 | 10 | .team-locations { 11 | padding:2em 0 3em; 12 | 13 | li { 14 | list-style: none; 15 | margin: 0em 1em 1em 1em; 16 | 17 | .location { 18 | background: white; 19 | padding: 1em 2em; 20 | display: block; 21 | width: 100%; 22 | 23 | > * { 24 | margin-bottom: .5em; 25 | display: block; 26 | } 27 | 28 | .title { 29 | margin-bottom: 1em; 30 | } 31 | 32 | .telephone, .email { 33 | display: block; 34 | } 35 | } 36 | } 37 | } 38 | 39 | @media all and (min-width: @media-desktop) { 40 | .container { 41 | padding-bottom: 0; 42 | } 43 | 44 | .form { 45 | width: 33%; 46 | float: left; 47 | } 48 | 49 | .map { 50 | width: 647px; 51 | float: left; 52 | display: block; 53 | clear: none; 54 | margin-left: 1em; 55 | position: relative; 56 | 57 | .pin { 58 | position: absolute; 59 | background-image: url('/images/contact-mappin.png'); 60 | width: 42px; 61 | height: 63px; 62 | margin-left: 30%; 63 | margin-top: 20%; 64 | } 65 | 66 | .map-background { 67 | width: 100%; 68 | } 69 | } 70 | 71 | .team-locations { 72 | display: -webkit-flex; 73 | display: -ms-flexbox; 74 | display: flex; 75 | 76 | -webkit-flex-wrap: wrap; 77 | -ms-flex-wrap: wrap; 78 | flex-wrap: wrap; 79 | 80 | li { 81 | display: -webkit-flex; 82 | display: -ms-flexbox; 83 | display: flex; 84 | width: 33.3%; 85 | margin: 0; 86 | padding: 1em; 87 | } 88 | } 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is where you define your application routes and controllers. 3 | * 4 | * Start by including the middleware you want to run for every request; 5 | * you can attach middleware to the pre('routes') and pre('render') events. 6 | * 7 | * For simplicity, the default setup for route controllers is for each to be 8 | * in its own file, and we import all the files in the /routes/views directory. 9 | * 10 | * Each of these files is a route controller, and is responsible for all the 11 | * processing that needs to happen for the route (e.g. loading data, handling 12 | * form submissions, rendering the view template, etc). 13 | * 14 | * Bind each route pattern your application should respond to in the function 15 | * that is exported from this module, following the examples below. 16 | * 17 | * See the Express application routing documentation for more information: 18 | * http://expressjs.com/api.html#app.VERB 19 | */ 20 | 21 | var _ = require('underscore'), 22 | keystone = require('keystone'), 23 | middleware = require('./middleware'), 24 | importRoutes = keystone.importer(__dirname); 25 | 26 | // Common Middleware 27 | keystone.pre('routes', middleware.initLocals); 28 | keystone.pre('render', middleware.flashMessages); 29 | 30 | // Import Route Controllers 31 | var routes = { 32 | views: importRoutes('./views') 33 | }; 34 | 35 | // Setup Route Bindings 36 | exports = module.exports = function(app) { 37 | 38 | // Views 39 | app.get('/', routes.views.index); 40 | //app.get('/blog/:category?', routes.views.blog); 41 | //app.get('/blog/post/:post', routes.views.post); 42 | //app.get('/gallery', routes.views.gallery); 43 | app.all('/ajax/contact', keystone.initAPI, routes.views.contact); 44 | 45 | // NOTE: To protect a route so that only admins can see it, use the requireUser middleware: 46 | // app.get('/protected', middleware.requireUser, routes.views.protected); 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /keystone.js: -------------------------------------------------------------------------------- 1 | if(process.env.NEWRELIC_LICENSE_KEY) require("newrelic"); 2 | 3 | var _ = require("underscore"); 4 | 5 | // Simulate config options from your production environment by 6 | // customising the .env file in your project's root folder. 7 | require('dotenv').load(); 8 | 9 | 10 | global.APP_ROOT = __dirname; 11 | 12 | // Require keystone 13 | var keystone = require('keystone'); 14 | 15 | 16 | // Initialise Keystone with your project's configuration. 17 | // See http://keystonejs.com/guide/config for available options 18 | // and documentation. 19 | 20 | 21 | keystone.init({ 22 | 23 | 'name': 'EthereumDev', 24 | 'brand': 'EthereumDev', 25 | 26 | 'less': 'public', 27 | 'static': 'public', 28 | 'favicon': 'public/favicon.ico', 29 | 'views': 'templates/views', 30 | 'view engine': 'jade', 31 | 32 | 'auto update': true, 33 | 'auth': true, 34 | 'user model': 'User', 35 | 'cookie secret': 'o9}#e0{8JCiy,gb^6PF49miMa.M(|*eBSPnl-5"DnzT0=:^W@ZqRgFJ34%}0
Thank you for your enquiry. We will get back to you shortly."+ 59 | "

EthDev team" 60 | }); 61 | }); 62 | }; 63 | 64 | Enquiry.defaultSort = '-createdAt'; 65 | Enquiry.defaultColumns = 'name, email, enquiryType, createdAt'; 66 | Enquiry.register(); 67 | -------------------------------------------------------------------------------- /routes/middleware.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file contains the common middleware used by your routes. 3 | * 4 | * Extend or replace these functions as your application requires. 5 | * 6 | * This structure is not enforced, and just a starting point. If 7 | * you have more middleware you may want to group it as separate 8 | * modules in your project's /lib directory. 9 | */ 10 | 11 | var _ = require('underscore'), 12 | querystring = require('querystring'), 13 | keystone = require('keystone'); 14 | 15 | 16 | /** 17 | Initialises the standard view locals 18 | 19 | The included layout depends on the navLinks array to generate 20 | the navigation in the header, you may wish to change this array 21 | or replace it with your own templates / logic. 22 | */ 23 | 24 | exports.initLocals = function(req, res, next) { 25 | 26 | var locals = res.locals; 27 | 28 | locals.navLinks = [ 29 | { label: 'Home', key: 'home', href: '#opener' }, 30 | { label: 'Mission Statement', key: 'mission-statement', href: '#mission' }, 31 | { label: 'Media', key: 'media', href: '#media' }, 32 | { label: 'Team', key: 'team', href: '#team' }, 33 | { label: 'Job Offers', key: 'job-offers', href: '#jobs' }, 34 | { label: 'Contact', key: 'contact', href: '#contact' } 35 | ]; 36 | 37 | locals.user = req.user; 38 | 39 | next(); 40 | 41 | }; 42 | 43 | 44 | /** 45 | Fetches and clears the flashMessages before a view is rendered 46 | */ 47 | 48 | exports.flashMessages = function(req, res, next) { 49 | 50 | var flashMessages = { 51 | info: req.flash('info'), 52 | success: req.flash('success'), 53 | warning: req.flash('warning'), 54 | error: req.flash('error') 55 | }; 56 | 57 | res.locals.messages = _.any(flashMessages, function(msgs) { return msgs.length; }) ? flashMessages : false; 58 | 59 | next(); 60 | 61 | }; 62 | 63 | 64 | /** 65 | Prevents people from accessing protected pages when they're not signed in 66 | */ 67 | 68 | exports.requireUser = function(req, res, next) { 69 | 70 | if (!req.user) { 71 | req.flash('error', 'Please sign in to access this page.'); 72 | res.redirect('/keystone/signin'); 73 | } else { 74 | next(); 75 | } 76 | 77 | }; 78 | -------------------------------------------------------------------------------- /templates/views/site/media.jade: -------------------------------------------------------------------------------- 1 | section#media 2 | .container 3 | h2 Media 4 | 5 | .mediawall 6 | .media-container 7 | each mediaItem in mediaSectionGalleryVideos 8 | a(class='media-item large video', 9 | href="https://www.youtube.com/watch?v=#{mediaItem.videoId}", 10 | data-date=mediaItem._.publishedDate.format("YYYY-DD-MM HH:MM:SS"), 11 | target="_blank") 12 | - var imageUrl = mediaItem.heroImage ? mediaItem._.heroImage.thumbnail(800, 800, {secure:true}) : '' 13 | img.background(src=imageUrl) 14 | .info 15 | h3.title= mediaItem.title 16 | if mediaItem.description 17 | p.description= mediaItem.description 18 | .play Play 19 | 20 | each mediaItem in mediaSectionGalleryLinks 21 | a(class='media-item link', 22 | href=mediaItem.secure_url, target="_blank", 23 | data-date=mediaItem._.publishedDate.format("YYYY-DD-MM HH:MM:SS")) 24 | - var imageUrl = mediaItem.heroImage ? mediaItem._.heroImage.thumbnail(400, 400, {secure:true}) : '' 25 | img.background(src=imageUrl) 26 | .info 27 | h3.title= mediaItem.title 28 | if mediaItem.description 29 | p.description= mediaItem.description 30 | 31 | each mediaItem in mediaSectionGalleryFiles 32 | if mediaItem.file 33 | div(class='media-item file', 34 | data-date=mediaItem._.publishedDate.format("YYYY-DD-MM HH:MM:SS")) 35 | - var iconUrl = mediaItem.icon ? mediaItem._.icon.thumbnail(200, 200, {secure:true}) : ''; 36 | img.background(src=iconUrl) 37 | .info 38 | h3.title= mediaItem.title 39 | if mediaItem.description 40 | p.description= mediaItem.description 41 | a.btn.btn-primary(href="/files/#{mediaItem.file.filename}", 42 | target="_blank") Download 43 | .grid-size 44 | .gutter-size 45 | 46 | .medianav 47 | button.left Left 48 | button.right Right 49 | 50 | +section_footer() 51 | 52 | -------------------------------------------------------------------------------- /public/styles/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Proxima Nova Bold"; 3 | src: url("../fonts/Proxima Nova Bold.eot"); 4 | src: local("☺"), 5 | url("../fonts/Proxima Nova Bold.woff") format("woff"), 6 | url("../fonts/Proxima Nova Bold.ttf") format("truetype"), 7 | url("../fonts/Proxima Nova Bold.svg") format("svg"); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | @font-face { 13 | font-family: "Proxima Nova Bold It"; 14 | src: url("../fonts/Proxima Nova Bold It.eot"); 15 | src: local("☺"), 16 | url("../fonts/Proxima Nova Bold It.svg") format("svg"), 17 | url("../fonts/Proxima Nova Bold It.ttf") format("truetype"), 18 | url("../fonts/Proxima Nova Bold It.woff") format("woff"); 19 | font-weight: normal; 20 | font-style: normal; 21 | } 22 | 23 | @font-face { 24 | font-family: "Proxima Nova Light"; 25 | src: url("../fonts/Proxima Nova Light.eot"); 26 | src: local("☺"), 27 | url("../fonts/Proxima Nova Light.svg") format("svg"), 28 | url("../fonts/Proxima Nova Light.ttf") format("truetype"), 29 | url("../fonts/Proxima Nova Light.woff") format("woff"); 30 | font-weight: normal; 31 | font-style: normal; 32 | } 33 | 34 | @font-face { 35 | font-family: "Proxima Nova Light It"; 36 | src: url("../fonts/Proxima Nova Light It.eot"); 37 | src: local("☺"), 38 | url("../fonts/Proxima Nova Light It.svg") format("svg"), 39 | url("../fonts/Proxima Nova Light It.ttf") format("truetype"), 40 | url("../fonts/Proxima Nova Light It.woff") format("woff"); 41 | font-weight: normal; 42 | font-style: normal; 43 | } 44 | 45 | @font-face { 46 | font-family: "Proxima Nova Reg"; 47 | src: url("../fonts/Proxima Nova Reg.eot"); 48 | src: local("☺"), 49 | url("../fonts/Proxima Nova Reg.svg") format("svg"), 50 | url("../fonts/Proxima Nova Reg.ttf") format("truetype"), 51 | url("../fonts/Proxima Nova Reg.woff") format("woff"); 52 | font-weight: normal; 53 | font-style: normal; 54 | } 55 | 56 | @font-face { 57 | font-family: "Proxima Nova Reg It"; 58 | src: url("../fonts/Proxima Nova Reg It.eot"); 59 | src: local("☺"), 60 | url("../fonts/Proxima Nova Reg It.svg") format("svg"), 61 | url("../fonts/Proxima Nova Reg It.ttf") format("truetype"), 62 | url("../fonts/Proxima Nova Reg It.woff") format("woff"); 63 | font-weight: normal; 64 | font-style: normal; 65 | } 66 | -------------------------------------------------------------------------------- /templates/views/site/contact.jade: -------------------------------------------------------------------------------- 1 | section#contact: .container 2 | h2 Contact Us 3 | 4 | .row 5 | form(method='post', action="/ajax/contact").form 6 | input(type='hidden', name='action', value='contact') 7 | .form-group 8 | label.form-label Name 9 | input(type='text', name='name.full', placeholder='NAME', required).form-control 10 | .form-group 11 | label.form-label Email 12 | input(type='email', name='email', placeholder='E-MAIL', required).form-control 13 | if enquiryTypes 14 | .form-group 15 | select(name='enquiryType', required).form-control 16 | option(value='') What are you contacting us about? 17 | each type in enquiryTypes 18 | option(value=type.value, selected=formData.enquiryType == type.value)= type.label 19 | .form-group 20 | label.form-label Message 21 | textarea(name='message', placeholder='MESSAGE', rows=6, required).form-control 22 | .form-group.form-actions 23 | button(type='submit').btn.btn-primary.btn-right Send 24 | 25 | .map 26 | img.map-background(src='/images/contact-mapbg.png') 27 | 28 | .row 29 | ul.team-locations 30 | each location in teamLocations 31 | li 32 | div.location 33 | h3= location.title 34 | .address 35 | if location.coordinates.number 36 | | !{location.coordinates.number + " " } 37 | if location.coordinates.name 38 | | !{location.coordinates.name + "
" } 39 | if location.coordinates.street1 40 | | !{location.coordinates.street1 + "
" } 41 | if location.coordinates.street2 42 | | !{location.coordinates.street2 + "
" } 43 | if location.coordinates.suburb 44 | | !{location.coordinates.suburb + "
" } 45 | if location.coordinates.state 46 | | !{location.coordinates.state + " " } 47 | if location.coordinates.postcode 48 | | !{location.coordinates.postcode + "
" } 49 | if location.coordinates.country 50 | | !{location.coordinates.country} 51 | a.telephone(href="tel:location.telephone")= location.telephone 52 | a.email(href="mailto:location.email")= location.email 53 | 54 | -------------------------------------------------------------------------------- /public/js/lib/masonry-horizontal.min.js: -------------------------------------------------------------------------------- 1 | !function(window){"use strict";function masonryHorizontalDefinition(getSize,LayoutMode){var MasonryHorizontal=LayoutMode.create("masonryHorizontal");return MasonryHorizontal.prototype._resetLayout=function(){this.getRowHeight(),this._getMeasurement("gutter","outerHeight"),this.rowHeight+=this.gutter,this.rows=Math.floor((this.isotope.size.innerHeight+this.gutter)/this.rowHeight),this.rows=Math.max(this.rows,1);var i=this.rows;for(this.rowXs=[];i--;)this.rowXs.push(0);this.maxX=0},MasonryHorizontal.prototype._getItemLayoutPosition=function(item){item.getSize();var rowSpan=Math.ceil(item.size.outerHeight/this.rowHeight);rowSpan=Math.min(rowSpan,this.rows);for(var rowGroup=this._getRowGroup(rowSpan),minimumX=Math.min.apply(Math,rowGroup),shortRowIndex=indexOf(rowGroup,minimumX),position={x:minimumX,y:this.rowHeight*shortRowIndex},setWidth=minimumX+item.size.outerWidth,setSpan=this.rows+1-rowGroup.length,i=0;setSpan>i;i++)this.rowXs[shortRowIndex+i]=setWidth;return position},MasonryHorizontal.prototype._getRowGroup=function(rowSpan){if(2>rowSpan)return this.rowXs;for(var rowGroup=[],groupCount=this.rows+1-rowSpan,i=0;groupCount>i;i++){var groupRowXs=this.rowXs.slice(i,i+rowSpan);rowGroup[i]=Math.max.apply(Math,groupRowXs)}return rowGroup},MasonryHorizontal.prototype._manageStamp=function(stamp){var stampSize=getSize(stamp),offset=this.isotope._getElementOffset(stamp),firstY=this.isotope.options.isOriginTop?offset.top:offset.bottom,lastY=firstY+stampSize.outerHeight,firstRow=Math.floor(firstY/this.rowHeight);firstRow=Math.max(0,firstRow);var lastRow=Math.floor(lastY/this.rowHeight);lastRow=Math.min(this.rows-1,lastRow);for(var stampMaxX=(this.isotope.options.isOriginLeft?offset.left:offset.right)+stampSize.outerWidth,i=firstRow;lastRow>=i;i++)this.rowXs[i]=Math.max(stampMaxX,this.rowXs[i])},MasonryHorizontal.prototype._getContainerSize=function(){return this.maxX=Math.max.apply(Math,this.rowXs),{width:this.maxX}},MasonryHorizontal.prototype.needsResizeLayout=function(){return this.needsVerticalResizeLayout()},MasonryHorizontal}var indexOf=Array.prototype.indexOf?function(items,value){return items.indexOf(value)}:function(items,value){for(var i=0,len=items.length;len>i;i++){var item=items[i];if(item===value)return i}return-1};"function"==typeof define&&define.amd?define(["get-size/get-size","isotope/js/layout-mode"],masonryHorizontalDefinition):masonryHorizontalDefinition(window.getSize,window.Isotope.LayoutMode)}(window); -------------------------------------------------------------------------------- /public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /public/images/jobs-plus-sprite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 25 | 26 | 27 | 28 | 30 | 32 | 33 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /templates/views/blog.jade: -------------------------------------------------------------------------------- 1 | extends ../layouts/default 2 | 3 | mixin post(post) 4 | .post(data-ks-editable=editable(user, { list: 'Post', id: post.id })) 5 | h2: a(href='/blog/post/' + post.slug)= post.title 6 | p.lead.text-muted Posted 7 | if post.publishedDate 8 | | on #{post._.publishedDate.format('MMMM Do, YYYY')} 9 | if post.categories && post.categories.length 10 | | in 11 | each cat, i in post.categories 12 | a(href='/blog/' + cat.key)= cat.name 13 | if i < post.categories.length - 1 14 | | , 15 | else 16 | | 17 | if post.author 18 | | by #{post.author.name.first} 19 | if post.image.exists 20 | img(src=post._.image.fit(160,160)).img.pull-right 21 | p!= post.content.brief 22 | if post.content.extended 23 | p.read-more: a(href='/blog/post/' + post.slug) Read more... 24 | 25 | block intro 26 | .container 27 | h1= data.category ? data.category.name : 'Blog' 28 | 29 | block content 30 | .container: .row 31 | .col-sm-8.col-md-9 32 | if filters.category && !data.category 33 | h3.text-muted Invalid Category. 34 | else 35 | if data.posts.results.length 36 | if data.posts.totalPages > 1 37 | h4.text-weight-normal Showing 38 | strong #{data.posts.first} 39 | | to 40 | strong #{data.posts.last} 41 | | of 42 | strong #{data.posts.total} 43 | | posts. 44 | else 45 | h4.text-weight-normal Showing #{utils.plural(data.posts.results.length, '* post')}. 46 | .blog 47 | each post in data.posts.results 48 | +post(post) 49 | 50 | if data.posts.totalPages > 1 51 | ul.pagination 52 | if data.posts.previous 53 | li: a(href='?page=' + data.posts.previous): span.glyphicon.glyphicon-chevron-left 54 | else 55 | li.disabled: a(href='?page=' + 1): span.glyphicon.glyphicon-chevron-left 56 | each p, i in data.posts.pages 57 | li(class=data.posts.currentPage == p ? 'active' : null) 58 | a(href='?page=' + (p == '...' ? (i ? data.posts.totalPages : 1) : p ))= p 59 | if data.posts.next 60 | li: a(href='?page=' + data.posts.next): span.glyphicon.glyphicon-chevron-right 61 | else 62 | li.disabled: a(href='?page=' + data.posts.totalPages): span.entypo.glyphicon.glyphicon-chevron-right 63 | else 64 | if data.category 65 | h3.text-muted There are no posts in the category #{data.category.name}. 66 | else 67 | h3.text-muted There are no posts yet. 68 | 69 | if data.categories.length 70 | .col-sm-4.col-md-3 71 | h2 Categories 72 | .list-group(style='margin-top: 70px;') 73 | a(href='/blog', class=!data.category ? 'active' : false).list-group-item All Categories 74 | each cat in data.categories 75 | a(href='/blog/' + cat.key, class=data.category && data.category.id == cat.id ? 'active' : false).list-group-item= cat.name 76 | -------------------------------------------------------------------------------- /templates/layouts/default.jade: -------------------------------------------------------------------------------- 1 | include ../mixins/flash-messages 2 | include ../mixins/section_footer 3 | 4 | doctype html 5 | html 6 | 7 | head 8 | meta(charset="utf-8") 9 | meta(name="viewport", content="width=device-width, initial-scale=1.0, max-width=device-width") 10 | meta(http-equiv="X-UA-Compatible" content="IE=edge") 11 | 12 | title= title || 'DEV' 13 | link(rel="shortcut icon", href="/favicon.png?v=1", type="image/x-icon") 14 | 15 | link(href="/styles/fonts.css", rel="stylesheet") 16 | link(href="/styles/site.min.css", rel="stylesheet") 17 | 18 | if user && user.canAccessKeystone 19 | link(href="/keystone/styles/content/editor.min.css", rel="stylesheet") 20 | 21 | block css 22 | 23 | block head 24 | 25 | body(id=currentSectionId) 26 | 27 | header.fixed-header 28 | nav(role="navigation").navbar 29 | button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') 30 | span.sr-only Toggle navigation 31 | 32 | .container.navgroup-container 33 | .scroller 34 | a.navbar-logo(href="#opener") 35 | ul.navgroup.navbar-nav.navbar-left 36 | each link in navLinks 37 | li: a(class="#{link.key}", href=link.href)= link.label 38 | ul.navgroup.navbar-nav.navbar-right 39 | if user 40 | if user.canAccessKeystone 41 | li: a(href='/keystone') Open Keystone 42 | li: a(href='/keystone/signout') Sign Out 43 | 44 | 45 | .page-content 46 | 47 | //- The Intro block appears above flash messages (used for temporary information display) 48 | block intro 49 | 50 | +flash-messages(messages) 51 | 52 | //- The content block should contain the body of your template's content 53 | block content 54 | 55 | footer: .container 56 | block footer 57 | 58 | 59 | //-[if lt IE 9] 60 | script(src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js") 61 | script(src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js") 62 | //-[endif] 63 | script(src='/js/lib/jquery/jquery-2.1.1.min.js') 64 | script(src='/js/lib/isotope.pkgd.min.js') 65 | script(src='/js/lib/masonry-horizontal.min.js') 66 | script(src='/js/lib/jquery.magnific-popup.min.js') 67 | script(src='/js/lib/packery-mode.pkgd.min.js') 68 | //- The KeystoneJS Content Editor provides support for ks-editable data attributes, 69 | //- which generate links to edit content for users who can access Keystone 70 | if user && user.canAccessKeystone 71 | script(src='/keystone/js/content/editor.js') 72 | 73 | script(src='/js/site.js') 74 | script. 75 | // Load the IFrame Player API code asynchronously. 76 | var tag = document.createElement('script'); 77 | tag.src = "https://www.youtube.com/player_api"; 78 | var firstScriptTag = document.getElementsByTagName('script')[0]; 79 | firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 80 | 81 | block js 82 | -------------------------------------------------------------------------------- /public/images/team-plus-sprite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 33 | 34 | 35 | 36 | 38 | 39 | 41 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /public/styles/site/layout.less: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-tap-highlight-color:rgba(0,0,0,0); 3 | -webkit-tap-highlight-color:transparent; 4 | -webkit-touch-callout: none; 5 | -webkit-overflow-scrolling: touch; 6 | outline:none; 7 | border:none; 8 | } 9 | 10 | section .container { 11 | overflow: hidden; 12 | } 13 | 14 | header.fixed-header { 15 | position: absolute; 16 | top: 0; 17 | left: 0; 18 | width: 100%; 19 | height: 100%; 20 | transition: height .4s ease-in-out; 21 | } 22 | 23 | .row { 24 | .clearfix(); 25 | } 26 | 27 | footer { 28 | margin-top: 30px; 29 | border-top: 1px solid @gray-lighter; 30 | padding-top: 30px; 31 | padding-bottom: 10em; 32 | background-color: white; 33 | z-index: 300; 34 | 35 | .container { 36 | text-align: center; 37 | margin-top:1em; 38 | } 39 | 40 | .footer-link { 41 | .ir(); 42 | display: inline-block; 43 | background-image: url('/images/footerlinks-sprite.svg'); 44 | background-size: 416px 35px; 45 | background-repeat: no-repeat; 46 | width: 36px; 47 | height: 35px; 48 | overflow: hidden; 49 | margin: 0 0.1em; 50 | 51 | &.facebook { background-position: 0 0; } 52 | &.twitter { background-position: -54px 0; } 53 | &.youtube { background-position: -108px 0; } 54 | &.reddit { background-position: -162px 0; } 55 | &.forum { background-position: -217px 0; } 56 | &.irc { background-position: -272px 0; } 57 | &.linkedin { background-position: -326px 0; } 58 | &.github { background-position: -381px 0; } 59 | } 60 | 61 | .copyright { 62 | font-size: 14pt; 63 | color: #4d4e4e; 64 | margin: 1em 1em; 65 | } 66 | } 67 | 68 | div.page-content { 69 | background-color: @gray-lighter; 70 | position: absolute; 71 | top: 0px; 72 | bottom: 0px; 73 | width: 100%; 74 | overflow: auto; 75 | -webkit-overflow-scrolling: touch; 76 | transition: top .4s ease-in-out, padding-top .4s ease-in-out, transform .4s ease-in-out; 77 | box-shadow: 0 0px 0px 4px rgba(0,0,0,0.2); 78 | /*padding-top: @page-header-height;*/ 79 | z-index: 0; 80 | } 81 | 82 | .show-navigation div.page-content { 83 | transform: translateX(-75%); 84 | } 85 | 86 | section { 87 | border-bottom: 1px solid @gray-lighter; 88 | padding-top: 72px; 89 | } 90 | 91 | .container { 92 | position: relative; 93 | width: 100%; 94 | margin-left: auto; 95 | margin-right: auto; 96 | transition: margin-left .3s ease-in-out, margin-right .3s ease-in-out; 97 | } 98 | 99 | @media all and (min-width: @media-desktop) { 100 | header.fixed-header { 101 | position: relative; 102 | height: @page-header-height; 103 | z-index: 400; 104 | } 105 | 106 | div.page-content { 107 | /*top: @page-header-height;*/ 108 | top: 0; 109 | padding-top: 0; 110 | } 111 | 112 | .show-navigation div.page-content { 113 | transform: translateX(0); 114 | } 115 | 116 | .container { 117 | width: 768pt; 118 | padding-bottom: 68px; 119 | } 120 | 121 | footer { 122 | margin-top: 0; 123 | padding-bottom: 4em; 124 | 125 | .container { 126 | padding-bottom: 0; 127 | } 128 | .footer-link { 129 | background-size: 917px 77px; 130 | width: 79px; 131 | height: 78px; 132 | margin: 0 1.4em; 133 | 134 | &.facebook { background-position: 0 0; } 135 | &.twitter { background-position: 14.2%; } 136 | &.youtube { background-position: 28.4% 0; } 137 | &.reddit { background-position: 42.9% 0; } 138 | &.forum { background-position: 57.3% 0; } 139 | &.irc { background-position: 71.5% 0; } 140 | &.linkedin { background-position: 85.8% 0; } 141 | &.github { background-position: 100% 0; } 142 | } 143 | } 144 | } 145 | 146 | .sr-only { 147 | .ir(); 148 | } 149 | -------------------------------------------------------------------------------- /public/styles/site/sections/mission.less: -------------------------------------------------------------------------------- 1 | #mission { 2 | 3 | .mission-statement { 4 | 5 | h2 { 6 | text-transform: uppercase; 7 | text-align: center; 8 | line-height: 1.3em; 9 | font-size: 22pt; 10 | } 11 | 12 | .collapsible-statement { 13 | .lead { 14 | transition: max-height .4s ease-in-out, margin-bottom .4s ease-in-out; 15 | max-height: 8em; 16 | overflow: hidden; 17 | margin-bottom: -2em; 18 | } 19 | 20 | &:after { 21 | content: " "; 22 | display: block; 23 | width: 100%; 24 | height: 2em; 25 | position: relative; 26 | left: -1px; 27 | background-image: linear-gradient(0deg, @gray-lighter 0%, fade(@gray-lighter, 0%)); 28 | } 29 | } 30 | 31 | .toggle-wrapper{ 32 | text-align: center; 33 | } 34 | 35 | .toggle-container { 36 | text-align: center; 37 | display: inline-block; 38 | background-image: url('/images/team-plus-sprite.svg'); 39 | overflow: hidden; 40 | background-position: 0px 0; 41 | width: 28px; 42 | height: 28px; 43 | margin: 0 auto 20px auto; 44 | cursor: pointer; 45 | background-size: 299px 28px; 46 | } 47 | 48 | &.expanded { 49 | 50 | .toggle-container { 51 | background-position: 327px 0; 52 | } 53 | 54 | .collapsible-statement { 55 | .lead { 56 | max-height: 10000px; //Ideally we would set this to 'none', but numeric value is required for transition 57 | margin-bottom: 0; 58 | } 59 | } 60 | } 61 | } 62 | 63 | .mission-steps .step { 64 | margin-bottom: 14%; 65 | } 66 | 67 | .mission-steps { 68 | width: 100%; 69 | padding: 0; 70 | text-align: center; 71 | counter-reset: mission-bullets; 72 | 73 | .step { 74 | list-style: none; 75 | margin-top: 0; 76 | counter-increment: mission-bullets; 77 | width: 100%; 78 | display: block; 79 | text-align: center; 80 | padding: 0 @mobile-padding; 81 | position: relative; 82 | 83 | img { 84 | max-width:100%; 85 | } 86 | 87 | h3 { 88 | margin-top: 0; 89 | margin-bottom: 47px; 90 | text-transform: uppercase; 91 | 92 | &:before { 93 | content: counter(mission-bullets) ". "; 94 | padding-right: .25em; 95 | display: inline-block; 96 | } 97 | } 98 | 99 | .video-container { 100 | width: 220px; 101 | height: 220px; 102 | margin: 0 auto; 103 | position: relative; 104 | overflow: hidden; 105 | border-radius: 50%; 106 | 107 | &:after { 108 | height: 100%; 109 | width: 100%; 110 | content: " "; 111 | position: absolute; 112 | background-image: url('/images/mission-overlay.png'); 113 | background-size: 100% 100%; 114 | top: 0; 115 | left: 0; 116 | } 117 | 118 | video { 119 | width: 221px; 120 | height: 221px; 121 | } 122 | 123 | } 124 | 125 | .info { 126 | margin-top: 47px; 127 | } 128 | } 129 | } 130 | 131 | @media all and (min-width: @media-desktop) { 132 | border-bottom: 0; 133 | 134 | .mission-steps .step { 135 | margin-bottom: 0; 136 | } 137 | 138 | .mission-steps { 139 | margin-bottom: -2em; 140 | .step { 141 | display: inline-block; 142 | vertical-align: top; 143 | width: 99% / 3; 144 | padding-left:12.5pt; 145 | padding-right:12.5pt; 146 | } 147 | } 148 | 149 | .section-footer { 150 | bottom: 0; 151 | background: white; 152 | margin-top: 39px * 3; 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /models/mission.js: -------------------------------------------------------------------------------- 1 | var keystone = require('keystone'), 2 | Types = keystone.Field.Types, 3 | async = require('async'); 4 | 5 | var MissionStatement = new keystone.List('MissionStatement', { 6 | autokey: { from: 'title', path: 'key', unique: true }, 7 | map: { name: 'title' }, 8 | defaultSort: '-publishedDate', 9 | sortable: true, 10 | nocreate: true 11 | }); 12 | 13 | MissionStatement.add({ 14 | title: { type: String, required: true, initial: true }, 15 | description: { type: Types.Markdown, required: true, initial: true }, 16 | publishedDate: { type: Date, default: function() { return Date.now() }, hidden: true }, 17 | editedDate: { type: Date, default: function() { return Date.now() }, hidden: true }, 18 | }); 19 | 20 | MissionStatement.register(); 21 | 22 | MissionStatement.model.find().count(function(err, count) { 23 | if (count > 0) return; 24 | 25 | console.log('Seeding mission statements') 26 | async.series([ 27 | function(done) { 28 | var msg0 = (new MissionStatement.model({ 29 | "key": "mission-statement", 30 | "title": "Mission Statement", 31 | "description": { 32 | "md": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nunc ex, porta nec dictum vel, finibus et odio. Praesent dictum nulla nunc, at tincidunt quam dapibus ac. Nunc quis dolor rutrum, ultricies justo a, consectetur mi.", 33 | "html": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nunc ex, porta nec dictum vel, finibus et odio. Praesent dictum nulla nunc, at tincidunt quam dapibus ac. Nunc quis dolor rutrum, ultricies justo a, consectetur mi." 34 | } 35 | })) 36 | msg0.save(function(err) { 37 | setTimeout(done, 10000, err); 38 | }) 39 | }, 40 | function(done) { 41 | var msg1 = (new MissionStatement.model({ 42 | "key": "refine-implement", 43 | "title": "Refine & Implement", 44 | "publishedDate": new Date(), 45 | "description": { 46 | "md": "Further refine and implement ethereum 1.0 as specified in the White Paper & Yellow Paper with 3 separate clean-room implementations", 47 | "html": "

Further refine and implement ethereum 1.0 as specified in the White Paper & Yellow Paper with 3 separate clean-room implementations

\n" 48 | } 49 | })) 50 | msg1.save(function(err) { 51 | setTimeout(done, 10000, err); 52 | }) 53 | }, 54 | function(done) { 55 | var msg2 = new MissionStatement.model({ 56 | "key": "develop-tools", 57 | "title": "Develop Tools", 58 | "publishedDate": new Date(), 59 | "description": { 60 | "md": "Develop the tools required to simplify the authoring, deployment and usage of contracts.", 61 | "html": "

Develop the tools required to simplify the authoring, deployment and usage of contracts.

\n" 62 | } 63 | }) 64 | msg2.save(function(err) { 65 | setTimeout(done, 10000, err); 66 | }) 67 | }, 68 | function(done) { 69 | var msg3 = new MissionStatement.model({ 70 | "key": "develop-key-technologies", 71 | "title": "Develop key technologies", 72 | "publishedDate": new Date(), 73 | "description": { 74 | "md": "Develop other key technologies in the quest for the decentralised web. this includes *Swarm* & *Whisper* as described before and further refinements to the ethereum (i.e. 2.0) and its tools.", 75 | "html": "

Develop other key technologies in the quest for the decentralised web. this includes Swarm & Whisper as described before and further refinements to the ethereum (i.e. 2.0) and its tools.

\n" 76 | } 77 | }) 78 | msg3.save(function(err) { 79 | setTimeout(done, 10000, err); 80 | }) 81 | } 82 | ], function() {}); 83 | }) 84 | -------------------------------------------------------------------------------- /public/styles/site/sections/team.less: -------------------------------------------------------------------------------- 1 | @profile-photo-mobile: 110px; 2 | @profile-photo-desktop: 220px; 3 | 4 | #team { 5 | text-align: center; 6 | 7 | .profile { 8 | width: 49%; 9 | text-align: center; 10 | vertical-align: top; 11 | display: inline-block; 12 | padding: 0 .5em; 13 | margin-bottom: 2em; 14 | cursor: pointer; 15 | 16 | &:after { 17 | content: " "; 18 | display: inline-block; 19 | background-image: url('/images/team-plus-sprite.svg'); 20 | background-size: 299px 28px; 21 | margin-top: .5em; 22 | width:28px; 23 | height:28px; 24 | } 25 | 26 | &.expanded:after { 27 | background-position-x: 100%; 28 | } 29 | 30 | .name { 31 | .clearfix(); 32 | margin-top:2em; 33 | margin-bottom:.5em; 34 | clear: both; 35 | 36 | .firstname, .lastname { 37 | text-transform: uppercase; 38 | color: @blue-light; 39 | text-align: center; 40 | font-size:18pt; 41 | } 42 | } 43 | 44 | .bio-copy { 45 | position: relative; 46 | overflow: hidden; 47 | height:2em; 48 | 49 | &:after { 50 | content: " "; 51 | display: block; 52 | height: 2em; 53 | position: absolute; 54 | bottom: 0; 55 | width: 100%; 56 | background-image: linear-gradient(0deg, @gray-lighter 0%, fade(@gray-lighter, 0%)); 57 | } 58 | 59 | p { 60 | margin-top: 0; 61 | } 62 | } 63 | 64 | .photo { 65 | width: 100%; 66 | max-width: @profile-photo-mobile; 67 | max-height: @profile-photo-mobile; 68 | min-height: @profile-photo-mobile; 69 | border-radius: 50%; 70 | overflow: hidden; 71 | position: relative; 72 | margin-left: auto; 73 | margin-right: auto; 74 | 75 | &:before { 76 | content: " "; 77 | display: block; 78 | padding-top: 0;//100%; 79 | } 80 | 81 | img { 82 | top: 100%; 83 | left: -25%; 84 | margin-left: -25%; 85 | min-width: 100%; 86 | min-height: 100%; 87 | max-width: 150%; 88 | display: block; 89 | } 90 | } 91 | } 92 | 93 | .lead-profile { 94 | overflow: hidden; 95 | 96 | .profile { 97 | width: 100%; 98 | cursor: default; 99 | 100 | .bio-copy { 101 | height: auto; 102 | 103 | &:after { 104 | display: none; 105 | } 106 | } 107 | 108 | .photo { 109 | max-width: 175px; 110 | max-height: 175px; 111 | margin-bottom: -1em; 112 | } 113 | 114 | .firstname, .lastname { 115 | display: inline-block; 116 | } 117 | 118 | .lastname { 119 | padding-left:.5em; 120 | } 121 | 122 | &:after { 123 | content: none; 124 | } 125 | } 126 | 127 | &.hidden { 128 | height: 0; 129 | } 130 | } 131 | 132 | @media all and (min-width: @media-desktop) { 133 | .lead-profile { 134 | display: none!important; 135 | } 136 | 137 | .profile { 138 | width: 24%; 139 | cursor: default; 140 | 141 | &.large { 142 | width: 33%; 143 | .photo { 144 | max-width: @profile-photo-desktop; 145 | max-height: @profile-photo-desktop; 146 | min-height: @profile-photo-desktop; 147 | } 148 | } 149 | 150 | &:after { 151 | content: none; 152 | } 153 | 154 | .bio-copy { 155 | height: auto; 156 | 157 | &:after { 158 | display: none; 159 | } 160 | } 161 | 162 | .photo { 163 | max-width: @profile-photo-desktop * .8; 164 | max-height: @profile-photo-desktop * .8; 165 | min-height: @profile-photo-desktop * .8; 166 | } 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /public/images/header-logo-mobile.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /public/styles/site/sections/jobs.less: -------------------------------------------------------------------------------- 1 | .dark-fade(angle) { 2 | background-image: linear-gradient(angle, @gray-dark 0%, fade(@gray-dark, 0%)); 3 | } 4 | 5 | 6 | #jobs { 7 | background-color: @gray-dark; 8 | color: @gray-lighter; 9 | 10 | padding-left: @mobile-padding; 11 | padding-right: @mobile-padding; 12 | 13 | .job-offers { 14 | .clearfix(); 15 | position: relative; 16 | list-style: none; 17 | margin-top: 0; 18 | margin-bottom: 0; 19 | margin-left: 0; 20 | padding-top: 1em; 21 | padding-bottom: 2em; 22 | padding-left: 1em; 23 | border-left: 1px solid white; 24 | 25 | &:before, &:after { 26 | position: absolute; 27 | display: block; 28 | width: 100%; 29 | height: 2em; 30 | left: -1px; 31 | content: " "; 32 | background-size: 100%; 33 | } 34 | 35 | &:before { 36 | top: 0; 37 | background-image: linear-gradient(180deg, @gray-dark 0%, fade(@gray-dark, 0%)); 38 | } 39 | 40 | &:after { 41 | bottom: 0; 42 | background-image: linear-gradient(0deg, @gray-dark 0%, fade(@gray-dark, 0%)); 43 | } 44 | 45 | .job-offer { 46 | line-height: normal; 47 | position: relative; 48 | margin-bottom: 1em; 49 | 50 | &:before { 51 | position: absolute; 52 | top: .25em; 53 | left: -0.95em; 54 | content: " "; 55 | display: block; 56 | width: .5em; 57 | height: .5em; 58 | background-color: @blue-light; 59 | border: 3px solid @gray-dark; 60 | border-radius: 50%; 61 | margin-left: -.5em; 62 | } 63 | 64 | &:after { 65 | content: " "; 66 | display: block; 67 | width: 100%; 68 | height: 2em; 69 | position: relative; 70 | left: -1px; 71 | background-image: linear-gradient(0deg, @gray-dark 0%, fade(@gray-dark, 0%)); 72 | } 73 | 74 | .title { 75 | color: @blue-light; 76 | text-transform: uppercase; 77 | padding-right: 1.5em; 78 | padding-top:11px; 79 | cursor: pointer; 80 | 81 | &:after { 82 | content: " "; 83 | display: inline-block; 84 | top: -2px; 85 | background-image: url('/images/jobs-plus-sprite.svg'); 86 | background-size: 63px 27px; 87 | overflow: hidden; 88 | background-position: 92px 0px; 89 | width: 28px; 90 | height: 27px; 91 | position: absolute; 92 | right: 0.15em; 93 | } 94 | } 95 | 96 | .description { 97 | transition: max-height .4s ease-in-out, margin-bottom .4s ease-in-out; 98 | max-height:7em; 99 | overflow: hidden; 100 | margin-bottom: -2em; 101 | 102 | p { 103 | margin-top: 0; 104 | } 105 | } 106 | 107 | .date { 108 | display: none; 109 | } 110 | 111 | button.apply { 112 | margin-top:1em; 113 | width: 100%; 114 | } 115 | 116 | &.expanded { 117 | 118 | .title:after { 119 | background-position: 0 0; 120 | } 121 | 122 | .description { 123 | max-height: 10000px; //Ideally we would set this to 'none', but numeric value is required for transition 124 | margin-bottom: 0; 125 | } 126 | } 127 | } 128 | } 129 | 130 | @media all and (min-width: @media-desktop) { 131 | padding-left: 0; 132 | padding-right: 0; 133 | @job-offer-width-desktop: 90%; 134 | 135 | .job-offers { 136 | .clearfix(); 137 | margin-left: 10%; 138 | padding-bottom: 6em; 139 | padding-left: 1.5em; 140 | 141 | .job-offer { 142 | width: @job-offer-width-desktop; 143 | margin-top: 3em; 144 | margin-bottom: 0; 145 | left: 0; 146 | 147 | &:before { 148 | top: 0.9em; 149 | left: -1.45em; 150 | } 151 | 152 | button.apply { 153 | margin-top:1em; 154 | width: 33%; 155 | } 156 | 157 | .date { 158 | color: @blue-light; 159 | display: block; 160 | position: absolute; 161 | top: 10px; 162 | left: -12.5%; 163 | text-align: right; 164 | } 165 | } 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /public/js/lib/masonry-horizontal.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * masonryHorizontal layout mode for Isotope 3 | * http://isotope.metafizzy.co 4 | */ 5 | 6 | /*jshint browser: true, strict: true, undef: true, unused: true */ 7 | 8 | ( function( window ) { 9 | 10 | 'use strict'; 11 | 12 | // -------------------------- helpers -------------------------- // 13 | 14 | var indexOf = Array.prototype.indexOf ? 15 | function( items, value ) { 16 | return items.indexOf( value ); 17 | } : 18 | function ( items, value ) { 19 | for ( var i=0, len = items.length; i < len; i++ ) { 20 | var item = items[i]; 21 | if ( item === value ) { 22 | return i; 23 | } 24 | } 25 | return -1; 26 | }; 27 | 28 | // -------------------------- definition -------------------------- // 29 | 30 | function masonryHorizontalDefinition( getSize, LayoutMode ) { 31 | // create an Outlayer layout class 32 | var MasonryHorizontal = LayoutMode.create('masonryHorizontal'); 33 | 34 | MasonryHorizontal.prototype._resetLayout = function() { 35 | this.getRowHeight(); 36 | this._getMeasurement( 'gutter', 'outerHeight' ); 37 | 38 | this.rowHeight += this.gutter; 39 | // measure rows 40 | this.rows = Math.floor( ( this.isotope.size.innerHeight + this.gutter ) / this.rowHeight ); 41 | this.rows = Math.max( this.rows, 1 ); 42 | 43 | // reset row Xs 44 | var i = this.rows; 45 | this.rowXs = []; 46 | while (i--) { 47 | this.rowXs.push( 0 ); 48 | } 49 | 50 | this.maxX = 0; 51 | }; 52 | 53 | MasonryHorizontal.prototype._getItemLayoutPosition = function( item ) { 54 | item.getSize(); 55 | // how many rows does this brick span 56 | var rowSpan = Math.ceil( item.size.outerHeight / this.rowHeight ); 57 | rowSpan = Math.min( rowSpan, this.rows ); 58 | 59 | var rowGroup = this._getRowGroup( rowSpan ); 60 | // get the minimum X value from the rows 61 | var minimumX = Math.min.apply( Math, rowGroup ); 62 | var shortRowIndex = indexOf( rowGroup, minimumX ); 63 | 64 | // position the brick 65 | var position = { 66 | x: minimumX, 67 | y: this.rowHeight * shortRowIndex 68 | }; 69 | 70 | // apply setHeight to necessary rows 71 | var setWidth = minimumX + item.size.outerWidth; 72 | var setSpan = this.rows + 1 - rowGroup.length; 73 | for ( var i = 0; i < setSpan; i++ ) { 74 | this.rowXs[ shortRowIndex + i ] = setWidth; 75 | } 76 | 77 | return position; 78 | }; 79 | 80 | /** 81 | * @param {Number} rowSpan - number of rows the element spans 82 | * @returns {Array} rowGroup 83 | */ 84 | MasonryHorizontal.prototype._getRowGroup = function( rowSpan ) { 85 | if ( rowSpan < 2 ) { 86 | // if brick spans only one row, use all the row Xs 87 | return this.rowXs; 88 | } 89 | 90 | var rowGroup = []; 91 | // how many different places could this brick fit horizontally 92 | var groupCount = this.rows + 1 - rowSpan; 93 | // for each group potential horizontal position 94 | for ( var i = 0; i < groupCount; i++ ) { 95 | // make an array of rowX values for that one group 96 | var groupRowXs = this.rowXs.slice( i, i + rowSpan ); 97 | // and get the max value of the array 98 | rowGroup[i] = Math.max.apply( Math, groupRowXs ); 99 | } 100 | return rowGroup; 101 | }; 102 | 103 | MasonryHorizontal.prototype._manageStamp = function( stamp ) { 104 | var stampSize = getSize( stamp ); 105 | var offset = this.isotope._getElementOffset( stamp ); 106 | // get the rows that this stamp affects 107 | var firstY = this.isotope.options.isOriginTop ? offset.top : offset.bottom; 108 | var lastY = firstY + stampSize.outerHeight; 109 | var firstRow = Math.floor( firstY / this.rowHeight ); 110 | firstRow = Math.max( 0, firstRow ); 111 | var lastRow = Math.floor( lastY / this.rowHeight ); 112 | lastRow = Math.min( this.rows - 1, lastRow ); 113 | // set rowXs to outside edge of the stamp 114 | var stampMaxX = ( this.isotope.options.isOriginLeft ? offset.left : offset.right ) + 115 | stampSize.outerWidth; 116 | for ( var i = firstRow; i <= lastRow; i++ ) { 117 | this.rowXs[i] = Math.max( stampMaxX, this.rowXs[i] ); 118 | } 119 | }; 120 | 121 | MasonryHorizontal.prototype._getContainerSize = function() { 122 | this.maxX = Math.max.apply( Math, this.rowXs ); 123 | 124 | return { 125 | width: this.maxX 126 | }; 127 | }; 128 | 129 | MasonryHorizontal.prototype.needsResizeLayout = function() { 130 | return this.needsVerticalResizeLayout(); 131 | }; 132 | 133 | return MasonryHorizontal; 134 | 135 | } 136 | 137 | if ( typeof define === 'function' && define.amd ) { 138 | // AMD 139 | define( [ 140 | 'get-size/get-size', 141 | 'isotope/js/layout-mode' 142 | ], 143 | masonryHorizontalDefinition ); 144 | } else { 145 | // browser global 146 | masonryHorizontalDefinition( 147 | window.getSize, 148 | window.Isotope.LayoutMode 149 | ); 150 | } 151 | 152 | })( window ); 153 | -------------------------------------------------------------------------------- /public/styles/site/header.less: -------------------------------------------------------------------------------- 1 | header.fixed-header { 2 | nav { 3 | background-color: #323232; 4 | width:100%; 5 | height: 100%; 6 | 7 | .navgroup-container { 8 | position: relative; 9 | top: 0; 10 | left: 12%; 11 | width: 75%; 12 | height: 100%; 13 | overflow-x: hidden; 14 | overflow-y: scroll; 15 | 16 | .scroller { 17 | min-height: 620px; 18 | position: relative; 19 | } 20 | 21 | /*transform: translateY(-100%);*/ 22 | /*transition: transform .4s ease-in-out;*/ 23 | } 24 | 25 | .navgroup { 26 | list-style: none; 27 | padding: 0; 28 | margin: 0; 29 | position: absolute; 30 | width: 100%; 31 | border-top: 1px solid #404040; 32 | 33 | li a { 34 | display: block; 35 | position: relative; 36 | border-bottom: 1px solid #404040; 37 | padding: 1em; 38 | padding-left: 3em; 39 | vertical-align: middle; 40 | color: white; 41 | text-transform: uppercase; 42 | 43 | &:before { 44 | position: relative; 45 | content: " "; 46 | display: inline-block; 47 | background-image:url('/images/header-icons-sprite.png'); 48 | background-position-x:0; 49 | background-repeat: no-repeat; 50 | width: 16px; 51 | height: 24px; 52 | margin-left: -24px; 53 | margin-right: 10px; 54 | vertical-align: middle; 55 | } 56 | 57 | &.home:before { background-position-y:1px; } 58 | &.mission-statement:before { background-position-y:-48px; } 59 | &.media:before { background-position-y:-98px; } 60 | &.team:before { background-position-y:-147px; } 61 | &.job-offers:before { background-position-y:-196px; } 62 | &.contact:before { background-position-y:-243px; } 63 | 64 | &.active { 65 | color: @blue-light; 66 | background-color: #252525; 67 | 68 | &:before { 69 | background-position-x:right; 70 | } 71 | } 72 | } 73 | } 74 | 75 | .navbar-left { 76 | top: 4em; 77 | } 78 | 79 | .navbar-logo { 80 | display: block; 81 | width: 199px; 82 | height: 30px; 83 | background-image: url('/images/ETH_DEV_LOGO.svg'); 84 | background-repeat: no-repeat; 85 | margin-top: 32px; 86 | margin-left: 20px; 87 | } 88 | 89 | .navbar-right { 90 | bottom: 0; 91 | } 92 | } 93 | 94 | .header-background { 95 | position: absolute; 96 | top: 0; 97 | left: 0; 98 | width: 100%; 99 | height: 2pt; 100 | transition: height .4s ease-in-out; 101 | } 102 | 103 | .navbar-toggle { 104 | .ir(); 105 | padding: 0; 106 | background-color: transparent; 107 | background-image: url('/images/header-menutoggle.png'); 108 | background-repeat: no-repeat; 109 | border: 0; 110 | width: 29pt; 111 | height: 31pt; 112 | position: fixed; 113 | right: 20pt; 114 | top: 12pt; 115 | transition: top .4s ease-in-out, margin-right .4s ease-in-out; 116 | z-index: 500; 117 | 118 | .show-navigation & { 119 | margin-right: 75%; 120 | } 121 | } 122 | 123 | @media all and (min-width: @media-desktop) { 124 | nav { 125 | height: @font-line-height-base * 2.5; 126 | background-color: rgba(50, 50, 50, 0.85); 127 | text-align: center; 128 | 129 | > .container { 130 | height: 100%; 131 | } 132 | 133 | .navgroup-container { 134 | transform: translateY(0%); 135 | display: inline-block; 136 | position: relative; 137 | bottom: 0; 138 | left: 0; 139 | margin-top: 0.4em; 140 | margin-left: 0px; 141 | width: 768pt; 142 | overflow: hidden; 143 | } 144 | 145 | .navgroup { 146 | width: auto; 147 | float: right; 148 | position: relative; 149 | border-top: 0; 150 | top: 0; 151 | 152 | &, > li, > li a { 153 | position: relative; 154 | display: inline-block; 155 | } 156 | 157 | > li { 158 | padding-right: 1em; 159 | float: left; 160 | 161 | a { 162 | vertical-align: middle; 163 | line-height: @page-header-height; 164 | height: 100%; 165 | padding: 0; 166 | border-bottom: 0; 167 | 168 | &:before { 169 | content: none; 170 | } 171 | 172 | &.active { 173 | background-color: transparent; 174 | } 175 | } 176 | } 177 | } 178 | 179 | .navbar-left { 180 | /*margin-right: 10px;*/ 181 | } 182 | 183 | .navbar-logo { 184 | /*content: none;*/ 185 | position: absolute; 186 | left: 18px; 187 | top: 7px; 188 | background-position: 0px 0; 189 | margin-top: 0; 190 | margin-left: 0; 191 | } 192 | } 193 | 194 | .navbar-toggle { 195 | top: -100%; 196 | } 197 | 198 | .header-background { 199 | height: 100%; 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /public/styles/site/sections/media.less: -------------------------------------------------------------------------------- 1 | @media-wall-gutter: 1em; 2 | 3 | #media { 4 | background-color: white; 5 | 6 | .grid-size { 7 | height: 46%; 8 | position: absolute; 9 | z-index: -1; 10 | } 11 | 12 | .gutter-size { 13 | position: absolute; 14 | z-index: -1; 15 | /*height: @media-wall-gutter;*/ 16 | height: 3%; 17 | } 18 | 19 | .medianav { 20 | display: none; 21 | pointer-events: none; 22 | 23 | .left, .right { 24 | pointer-events: all; 25 | } 26 | } 27 | 28 | .mediawall { 29 | z-index: 100; 30 | height: 27em; 31 | margin-left: @mobile-padding; 32 | margin-right: @mobile-padding; 33 | position: relative; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | -webkit-overflow-scrolling: touch; 37 | 38 | .media-container { 39 | height: 100%; 40 | } 41 | 42 | .media-item { 43 | width: 47.5%; 44 | position: relative; 45 | display: block; 46 | margin: 0 2.5% 2.5% 0;//@media-wall-gutter; 47 | overflow: hidden; 48 | max-height: 45%; 49 | 50 | &:before { 51 | content: " "; 52 | display: block; 53 | padding-top: 100%; 54 | } 55 | 56 | &.large { 57 | width: 97.5%; 58 | max-height: 94.5%; 59 | } 60 | 61 | .background { 62 | min-width: 100%; 63 | min-height: 100%; 64 | display: block; 65 | position: absolute; 66 | top: 0; 67 | max-width: 100%; 68 | /*width: 100%;*/ 69 | } 70 | 71 | .info { 72 | color: @gray-dark; 73 | position: absolute; 74 | bottom: 0; 75 | width: 100%; 76 | background-color: rgba(240, 240, 240, 0.65); 77 | padding: 1em; 78 | font-size: 12pt; 79 | line-height: 1.3em; 80 | 81 | > * { 82 | margin-top: 0; 83 | } 84 | 85 | h3 { 86 | font-size: inherit; 87 | margin-bottom:.5em; 88 | line-height:1.3em; 89 | height:2.2em; 90 | overflow: hidden; 91 | text-transform: uppercase; 92 | } 93 | 94 | .description { 95 | display: none; 96 | margin-bottom: 0; 97 | line-height: 1.2em; 98 | font-size: .8em; 99 | } 100 | } 101 | 102 | &.file, &.link { 103 | background-color: @gray-lighter; 104 | text-align: center; 105 | 106 | .info { 107 | text-align: left; 108 | 109 | .description { 110 | margin-top: 1em; 111 | margin-bottom: 1em; 112 | } 113 | } 114 | } 115 | 116 | &.video { 117 | cursor: pointer; 118 | 119 | .play { 120 | .ir(); 121 | position: absolute; 122 | background-color: transparent; 123 | border: 0; 124 | background-image:url('/images/media-playbutton.svg'); 125 | background-size: contain; 126 | background-repeat: no-repeat; 127 | background-position: 50% 50%; 128 | width: 20%; 129 | height: 20%; 130 | top: 50%; 131 | left: 50%; 132 | margin-top: -15%; 133 | margin-left: -10%; 134 | } 135 | } 136 | 137 | &.link { 138 | h3 { 139 | height: auto; 140 | } 141 | } 142 | 143 | &.file { 144 | .background { 145 | position: absolute; 146 | display: inline-block; 147 | vertical-align: middle; 148 | top:8%; 149 | width: 30%; 150 | min-width: 0px; 151 | min-height: 0px; 152 | margin-left: -15%; 153 | left: 50%; 154 | } 155 | 156 | .info { 157 | background-color: transparent; 158 | } 159 | 160 | .btn { 161 | width: 100%; 162 | font-size: 12pt!important; 163 | } 164 | } 165 | } 166 | } 167 | 168 | @media all and (min-width: @media-desktop) { 169 | position: relative; 170 | 171 | .grid-size { 172 | width:auto; 173 | margin-left: 1em; 174 | margin-right: 66%; 175 | height: 182px; 176 | } 177 | 178 | .gutter-size { 179 | height: 1em; 180 | width: 1em; 181 | } 182 | 183 | .medianav { 184 | display: block; 185 | position: absolute; 186 | height: 100%; 187 | width: 768pt; 188 | top: 0; 189 | left: 50%; 190 | z-index: 350; 191 | margin-left: -768pt / 2; 192 | 193 | .left, .right { 194 | .ir(); 195 | display: block; 196 | position: absolute; 197 | top: 50%; 198 | margin-top: -42px; 199 | left: -8em; 200 | border: 0; 201 | width:87px; 202 | height:85px; 203 | background-image: url('/images/media-navbuttons-sprite.svg'); 204 | background-position: 1px 0; 205 | background-size: 397px 85px; 206 | background-repeat:no-repeat; 207 | background-color: transparent; 208 | } 209 | 210 | .right { 211 | background-position: right 0; 212 | left: auto; 213 | right: -7.5em; 214 | } 215 | } 216 | 217 | .mediawall { 218 | height: 46em; 219 | margin-left: @media-wall-gutter * .5; 220 | margin-right: @media-wall-gutter * .5; 221 | padding-left: 0; 222 | padding-right: 0; 223 | overflow: hidden; 224 | 225 | .media-item { 226 | width: 32%; 227 | /*width: @media-wall-gutter * 21;*/ 228 | margin:0 @media-wall-gutter @media-wall-gutter 0; 229 | 230 | &.large { 231 | width: 66.2%; 232 | /*width: @media-wall-gutter * 43;*/ 233 | } 234 | 235 | .info { 236 | h3 { 237 | height: auto; 238 | } 239 | 240 | .description { 241 | margin-top: .5em; 242 | display: block; 243 | font-size: 1em; 244 | } 245 | } 246 | } 247 | } 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /public/images/media-navbuttons-sprite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 71 | 72 | 73 | 74 | 76 | 78 | 79 | -------------------------------------------------------------------------------- /public/images/media-playbutton.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 112 | 113 | 114 | 115 | 116 | 118 | 119 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /public/styles/magnific-popup.css: -------------------------------------------------------------------------------- 1 | /* Magnific Popup CSS */ 2 | .mfp-bg { 3 | top: 0; 4 | left: 0; 5 | width: 100%; 6 | height: 100%; 7 | z-index: 1042; 8 | overflow: hidden; 9 | position: fixed; 10 | background: #0b0b0b; 11 | opacity: 0.8; 12 | filter: alpha(opacity=80); } 13 | 14 | .mfp-wrap { 15 | top: 0; 16 | left: 0; 17 | width: 100%; 18 | height: 100%; 19 | z-index: 1043; 20 | position: fixed; 21 | outline: none !important; 22 | -webkit-backface-visibility: hidden; } 23 | 24 | .mfp-container { 25 | text-align: center; 26 | position: absolute; 27 | width: 100%; 28 | height: 100%; 29 | left: 0; 30 | top: 0; 31 | padding: 0 8px; 32 | -webkit-box-sizing: border-box; 33 | -moz-box-sizing: border-box; 34 | box-sizing: border-box; } 35 | 36 | .mfp-container:before { 37 | content: ''; 38 | display: inline-block; 39 | height: 100%; 40 | vertical-align: middle; } 41 | 42 | .mfp-align-top .mfp-container:before { 43 | display: none; } 44 | 45 | .mfp-content { 46 | position: relative; 47 | display: inline-block; 48 | vertical-align: middle; 49 | margin: 0 auto; 50 | text-align: left; 51 | z-index: 1045; } 52 | 53 | .mfp-inline-holder .mfp-content, .mfp-ajax-holder .mfp-content { 54 | width: 100%; 55 | cursor: auto; } 56 | 57 | .mfp-ajax-cur { 58 | cursor: progress; } 59 | 60 | .mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close { 61 | cursor: -moz-zoom-out; 62 | cursor: -webkit-zoom-out; 63 | cursor: zoom-out; } 64 | 65 | .mfp-zoom { 66 | cursor: pointer; 67 | cursor: -webkit-zoom-in; 68 | cursor: -moz-zoom-in; 69 | cursor: zoom-in; } 70 | 71 | .mfp-auto-cursor .mfp-content { 72 | cursor: auto; } 73 | 74 | .mfp-close, .mfp-arrow, .mfp-preloader, .mfp-counter { 75 | -webkit-user-select: none; 76 | -moz-user-select: none; 77 | user-select: none; } 78 | 79 | .mfp-loading.mfp-figure { 80 | display: none; } 81 | 82 | .mfp-hide { 83 | display: none !important; } 84 | 85 | .mfp-preloader { 86 | color: #cccccc; 87 | position: absolute; 88 | top: 50%; 89 | width: auto; 90 | text-align: center; 91 | margin-top: -0.8em; 92 | left: 8px; 93 | right: 8px; 94 | z-index: 1044; } 95 | .mfp-preloader a { 96 | color: #cccccc; } 97 | .mfp-preloader a:hover { 98 | color: white; } 99 | 100 | .mfp-s-ready .mfp-preloader { 101 | display: none; } 102 | 103 | .mfp-s-error .mfp-content { 104 | display: none; } 105 | 106 | button.mfp-close, button.mfp-arrow { 107 | overflow: visible; 108 | cursor: pointer; 109 | background: transparent; 110 | border: 0; 111 | -webkit-appearance: none; 112 | display: block; 113 | outline: none; 114 | padding: 0; 115 | z-index: 1046; 116 | -webkit-box-shadow: none; 117 | box-shadow: none; } 118 | button::-moz-focus-inner { 119 | padding: 0; 120 | border: 0; } 121 | 122 | .mfp-close { 123 | width: 44px; 124 | height: 44px; 125 | line-height: 44px; 126 | position: absolute; 127 | right: 0; 128 | top: 0; 129 | text-decoration: none; 130 | text-align: center; 131 | opacity: 0.65; 132 | filter: alpha(opacity=65); 133 | padding: 0 0 18px 10px; 134 | color: white; 135 | font-style: normal; 136 | font-size: 28px; 137 | font-family: Arial, Baskerville, monospace; } 138 | .mfp-close:hover, .mfp-close:focus { 139 | opacity: 1; 140 | filter: alpha(opacity=100); } 141 | .mfp-close:active { 142 | top: 1px; } 143 | 144 | .mfp-close-btn-in .mfp-close { 145 | color: #333333; } 146 | 147 | .mfp-image-holder .mfp-close, .mfp-iframe-holder .mfp-close { 148 | color: white; 149 | right: -6px; 150 | text-align: right; 151 | padding-right: 6px; 152 | width: 100%; } 153 | 154 | .mfp-counter { 155 | position: absolute; 156 | top: 0; 157 | right: 0; 158 | color: #cccccc; 159 | font-size: 12px; 160 | line-height: 18px; } 161 | 162 | .mfp-arrow { 163 | position: absolute; 164 | opacity: 0.65; 165 | filter: alpha(opacity=65); 166 | margin: 0; 167 | top: 50%; 168 | margin-top: -55px; 169 | padding: 0; 170 | width: 90px; 171 | height: 110px; 172 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } 173 | .mfp-arrow:active { 174 | margin-top: -54px; } 175 | .mfp-arrow:hover, .mfp-arrow:focus { 176 | opacity: 1; 177 | filter: alpha(opacity=100); } 178 | .mfp-arrow:before, .mfp-arrow:after, .mfp-arrow .mfp-b, .mfp-arrow .mfp-a { 179 | content: ''; 180 | display: block; 181 | width: 0; 182 | height: 0; 183 | position: absolute; 184 | left: 0; 185 | top: 0; 186 | margin-top: 35px; 187 | margin-left: 35px; 188 | border: medium inset transparent; } 189 | .mfp-arrow:after, .mfp-arrow .mfp-a { 190 | border-top-width: 13px; 191 | border-bottom-width: 13px; 192 | top: 8px; } 193 | .mfp-arrow:before, .mfp-arrow .mfp-b { 194 | border-top-width: 21px; 195 | border-bottom-width: 21px; 196 | opacity: 0.7; } 197 | 198 | .mfp-arrow-left { 199 | left: 0; } 200 | .mfp-arrow-left:after, .mfp-arrow-left .mfp-a { 201 | border-right: 17px solid white; 202 | margin-left: 31px; } 203 | .mfp-arrow-left:before, .mfp-arrow-left .mfp-b { 204 | margin-left: 25px; 205 | border-right: 27px solid #3f3f3f; } 206 | 207 | .mfp-arrow-right { 208 | right: 0; } 209 | .mfp-arrow-right:after, .mfp-arrow-right .mfp-a { 210 | border-left: 17px solid white; 211 | margin-left: 39px; } 212 | .mfp-arrow-right:before, .mfp-arrow-right .mfp-b { 213 | border-left: 27px solid #3f3f3f; } 214 | 215 | .mfp-iframe-holder { 216 | padding-top: 40px; 217 | padding-bottom: 40px; } 218 | .mfp-iframe-holder .mfp-content { 219 | line-height: 0; 220 | width: 100%; 221 | max-width: 900px; } 222 | .mfp-iframe-holder .mfp-close { 223 | top: -40px; } 224 | 225 | .mfp-iframe-scaler { 226 | width: 100%; 227 | height: 0; 228 | overflow: hidden; 229 | padding-top: 56.25%; } 230 | .mfp-iframe-scaler iframe { 231 | position: absolute; 232 | display: block; 233 | top: 0; 234 | left: 0; 235 | width: 100%; 236 | height: 100%; 237 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); 238 | background: black; } 239 | 240 | /* Main image in popup */ 241 | img.mfp-img { 242 | width: auto; 243 | max-width: 100%; 244 | height: auto; 245 | display: block; 246 | line-height: 0; 247 | -webkit-box-sizing: border-box; 248 | -moz-box-sizing: border-box; 249 | box-sizing: border-box; 250 | padding: 40px 0 40px; 251 | margin: 0 auto; } 252 | 253 | /* The shadow behind the image */ 254 | .mfp-figure { 255 | line-height: 0; } 256 | .mfp-figure:after { 257 | content: ''; 258 | position: absolute; 259 | left: 0; 260 | top: 40px; 261 | bottom: 40px; 262 | display: block; 263 | right: 0; 264 | width: auto; 265 | height: auto; 266 | z-index: -1; 267 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); 268 | background: #444444; } 269 | .mfp-figure small { 270 | color: #bdbdbd; 271 | display: block; 272 | font-size: 12px; 273 | line-height: 14px; } 274 | .mfp-figure figure { 275 | margin: 0; } 276 | 277 | .mfp-bottom-bar { 278 | margin-top: -36px; 279 | position: absolute; 280 | top: 100%; 281 | left: 0; 282 | width: 100%; 283 | cursor: auto; } 284 | 285 | .mfp-title { 286 | text-align: left; 287 | line-height: 18px; 288 | color: #f3f3f3; 289 | word-wrap: break-word; 290 | padding-right: 36px; } 291 | 292 | .mfp-image-holder .mfp-content { 293 | max-width: 100%; } 294 | 295 | .mfp-gallery .mfp-image-holder .mfp-figure { 296 | cursor: pointer; } 297 | 298 | @media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) { 299 | /** 300 | * Remove all paddings around the image on small screen 301 | */ 302 | .mfp-img-mobile .mfp-image-holder { 303 | padding-left: 0; 304 | padding-right: 0; } 305 | .mfp-img-mobile img.mfp-img { 306 | padding: 0; } 307 | .mfp-img-mobile .mfp-figure:after { 308 | top: 0; 309 | bottom: 0; } 310 | .mfp-img-mobile .mfp-figure small { 311 | display: inline; 312 | margin-left: 5px; } 313 | .mfp-img-mobile .mfp-bottom-bar { 314 | background: rgba(0, 0, 0, 0.6); 315 | bottom: 0; 316 | margin: 0; 317 | top: auto; 318 | padding: 3px 5px; 319 | position: fixed; 320 | -webkit-box-sizing: border-box; 321 | -moz-box-sizing: border-box; 322 | box-sizing: border-box; } 323 | .mfp-img-mobile .mfp-bottom-bar:empty { 324 | padding: 0; } 325 | .mfp-img-mobile .mfp-counter { 326 | right: 5px; 327 | top: 3px; } 328 | .mfp-img-mobile .mfp-close { 329 | top: 0; 330 | right: 0; 331 | width: 35px; 332 | height: 35px; 333 | line-height: 35px; 334 | background: rgba(0, 0, 0, 0.6); 335 | position: fixed; 336 | text-align: center; 337 | padding: 0; } } 338 | 339 | @media all and (max-width: 900px) { 340 | .mfp-arrow { 341 | -webkit-transform: scale(0.75); 342 | transform: scale(0.75); } 343 | .mfp-arrow-left { 344 | -webkit-transform-origin: 0; 345 | transform-origin: 0; } 346 | .mfp-arrow-right { 347 | -webkit-transform-origin: 100%; 348 | transform-origin: 100%; } 349 | .mfp-container { 350 | padding-left: 6px; 351 | padding-right: 6px; } } 352 | 353 | .mfp-ie7 .mfp-img { 354 | padding: 0; } 355 | .mfp-ie7 .mfp-bottom-bar { 356 | width: 600px; 357 | left: 50%; 358 | margin-left: -300px; 359 | margin-top: 5px; 360 | padding-bottom: 5px; } 361 | .mfp-ie7 .mfp-container { 362 | padding: 0; } 363 | .mfp-ie7 .mfp-content { 364 | padding-top: 44px; } 365 | .mfp-ie7 .mfp-close { 366 | top: 0; 367 | right: 0; 368 | padding-top: 0; } 369 | -------------------------------------------------------------------------------- /public/js/site.js: -------------------------------------------------------------------------------- 1 | !function(window) { 2 | 'use strict'; 3 | 4 | var mediaQueryDesktop = 'screen and (min-width: 768pt)', 5 | debounce, 6 | onClick_jobOffer, 7 | onClick_toggleMissionStatement, 8 | onSubmit_contactForm, 9 | onClick_sectionTab, 10 | onClick_profile, 11 | onClick_jobOfferApply, 12 | onClick_navButton, 13 | onClick_navLink, 14 | onResize_window, 15 | onClick_medianav, 16 | onScroll_pageContent, 17 | $pageContent, 18 | $video, 19 | $mediawall, 20 | mediaPos; 21 | 22 | debounce = function(func, wait, immediate) { 23 | var timeout; 24 | return function() { 25 | var context = this, args = arguments; 26 | var later = function() { 27 | timeout = null; 28 | if (!immediate) func.apply(context, args); 29 | }; 30 | var callNow = immediate && !timeout; 31 | clearTimeout(timeout); 32 | timeout = setTimeout(later, wait); 33 | if (callNow) func.apply(context, args); 34 | }; 35 | }; 36 | 37 | $(function() { 38 | var isMediaWallActive = false, 39 | matchDesktop; 40 | 41 | mediaPos = 0; 42 | 43 | $pageContent = $('.page-content'); 44 | 45 | $mediawall = $('#media .mediawall .media-container'); 46 | 47 | $video = $('#opener video'); 48 | 49 | $video[0].addEventListener("ended", function(){ 50 | //$video[0].load(); 51 | this.src = this.src; 52 | },false); 53 | 54 | matchDesktop = matchMedia(mediaQueryDesktop); 55 | 56 | $('#jobs').on('click', '.job-offer button.apply', onClick_jobOfferApply); 57 | $('#jobs').on('click', '.job-offer', onClick_jobOffer); 58 | $('#mission').on('click', '.toggle-container', onClick_toggleMissionStatement); 59 | $('#contact').on('submit', 'form', onSubmit_contactForm); 60 | $('body').on('click', '.section-footer .tab', onClick_sectionTab); 61 | $('#team').on('click', '.profile', onClick_profile); 62 | $('#media').on('click', '.medianav button', onClick_medianav); 63 | $('header button[data-toggle]').on('click', onClick_navButton); 64 | $('header').on('click', '.navgroup li a', onClick_navLink); 65 | 66 | $mediawall.isotope({ 67 | layoutMode: 'packery', 68 | getSortData: { 69 | name: function(elem) { 70 | return $(elem).attr('data-date'); 71 | } 72 | }, 73 | itemSelector: '.media-item', 74 | sortBy: 'name', 75 | sortAscending: false, 76 | containerStyle: {}, 77 | packery: { 78 | isHorizontal: true 79 | //columnWidth: '#media .grid-size', 80 | //gutter: '#media .gutter-size' 81 | }, 82 | masonryHorizontal: { 83 | rowHeight: $mediawall.children('.grid-size').get(1), 84 | gutter: $mediawall.children('.gutter-size').get(0) 85 | } 86 | }); 87 | 88 | $(window).on('resize', onResize_window); 89 | $(document).load(function(ev) { 90 | $($0).isotope('layout'); 91 | }); 92 | $pageContent.on('scroll', debounce(onScroll_pageContent, 100)); 93 | 94 | onScroll_pageContent(null); 95 | $(document.body).on('load', function() { 96 | onScroll_pageContent(null); 97 | }); 98 | 99 | positionMapPins($('#contact .map .pin')); 100 | }); 101 | 102 | function positionMapPins($pins) { 103 | var R = 70; 104 | 105 | $pins.each(function(i, e) { 106 | var $pin = $(e), 107 | coords = $pin.data('coords').split(','); 108 | 109 | //debugger 110 | 111 | $pin.css({ 112 | left: R * Math.cos(coords[1]) * Math.cos(coords[0]) + 'px', 113 | top: R * Math.cos(coords[1]) * Math.sin(coords[0]) + 'px' 114 | }); 115 | }); 116 | } 117 | 118 | function scrollPosition(iterOffsetParent) { 119 | var scrollOffset = 0; 120 | iterOffsetParent = $(iterOffsetParent)[0]; 121 | while (iterOffsetParent !== $('.page-content').get(0)) { 122 | scrollOffset += iterOffsetParent.offsetTop; 123 | iterOffsetParent = iterOffsetParent.offsetParent; 124 | } 125 | return scrollOffset; 126 | } 127 | 128 | function isDesktop() { 129 | return matchMedia('screen and (min-width: 768pt)').matches; 130 | } 131 | 132 | onScroll_pageContent = function(ev) { 133 | var baseOffset = 0; 134 | $('section').each(function(i, e) { 135 | var middle, 136 | scrollPos; 137 | 138 | try { 139 | scrollPos = scrollPosition(e) + e.offsetHeight; 140 | } catch (e) { 141 | return true; 142 | } 143 | 144 | if (i === 0) baseOffset = scrollPos; 145 | middle = $pageContent.scrollTop() + baseOffset; 146 | 147 | if (middle <= scrollPos) { 148 | $('header nav li a[href=#' + e.id + ']') 149 | .addClass('active') 150 | .parent() 151 | .siblings().children('a') 152 | .removeClass('active'); 153 | 154 | return false; 155 | } 156 | }); 157 | }; 158 | 159 | onClick_navLink = function() { 160 | if (matchMedia('screen and (min-width: 768pt)').matches) return true; 161 | 162 | $(document.body).removeClass('show-navigation'); 163 | }; 164 | 165 | onClick_navButton = function(ev) { 166 | $(document.body).toggleClass('show-navigation'); 167 | 168 | if ($(document.body).hasClass('show-navigation')) { 169 | $('.page-content').one('click', function() { 170 | $(document.body).removeClass('show-navigation'); 171 | }); 172 | } 173 | }; 174 | 175 | onResize_window = function(ev) { 176 | $mediawall.isotope(); 177 | }; 178 | 179 | onClick_profile = function(ev) { 180 | var photoUrl = $(ev.currentTarget).find('.photo img').attr('src'), 181 | firstname = $(ev.currentTarget).find('.firstname').text(), 182 | lastname = $(ev.currentTarget).find('.lastname').text(), 183 | bio = $(ev.currentTarget).find('.bio-copy').clone(), 184 | $leadProfile = $(ev.delegateTarget).find('.lead-profile'), 185 | scrollOffset = 0, 186 | iterOffsetParent = $leadProfile.get(0); 187 | 188 | if (matchMedia('screen and (min-width: 768pt)').matches) return true; 189 | 190 | scrollOffset = scrollPosition(iterOffsetParent); 191 | 192 | $(ev.currentTarget) 193 | .addClass('expanded') 194 | .siblings() 195 | .removeClass('expanded'); 196 | 197 | $leadProfile.clearQueue().fadeOut(300, function() { 198 | 199 | $leadProfile.find('.photo img').attr('src', photoUrl); 200 | $leadProfile.find('.firstname').text(firstname); 201 | $leadProfile.find('.lastname').text(lastname); 202 | $leadProfile.find('.bio-copy').replaceWith(bio); 203 | 204 | $leadProfile.removeClass('hidden'); 205 | 206 | $leadProfile.fadeIn(300); 207 | 208 | $('.page-content') 209 | .clearQueue() 210 | .animate({ 211 | scrollTop: scrollOffset - 24 212 | }); 213 | }); 214 | }; 215 | 216 | onClick_medianav = function(ev) { 217 | 218 | ev.preventDefault(); 219 | 220 | var $target = $(ev.currentTarget), 221 | $mediawall = $('#media .mediawall'), 222 | mediawallWidth = $mediawall.width(); 223 | 224 | var numItems = $mediawall.find('.media-item.large').length; 225 | var positions = [0]; 226 | 227 | for (var i = 1; i < numItems; i++) { 228 | positions.push(i * mediawallWidth * .67); 229 | } 230 | 231 | if ($target.hasClass('left')) { 232 | mediaPos--; 233 | } else { 234 | mediaPos++; 235 | } 236 | 237 | mediaPos = Math.max(0, Math.min(mediaPos, numItems - 1)); 238 | $mediawall.clearQueue().animate({scrollLeft: positions[mediaPos]}, 300); 239 | }; 240 | 241 | onClick_jobOffer = function(ev) { 242 | var $target = $(ev.currentTarget), 243 | $parent = $target, 244 | scrollOffset = 0, 245 | iterOffsetParent = $parent.get(0); 246 | 247 | var isExpanded = $parent.hasClass('expanded'); 248 | 249 | if (isExpanded) { 250 | $parent.removeClass('expanded'); 251 | } 252 | else { 253 | $parent 254 | .addClass('expanded') 255 | .siblings() 256 | .removeClass('expanded'); 257 | } 258 | 259 | setTimeout(function() { 260 | scrollOffset = scrollPosition(iterOffsetParent); 261 | 262 | //debugger 263 | $('.page-content') 264 | .clearQueue() 265 | .animate({ 266 | scrollTop: scrollOffset - parseInt($target.css('marginTop')) - 64 267 | }, 300); 268 | }, 410); 269 | }; 270 | 271 | onClick_jobOfferApply = function(ev) { 272 | var $job = $(ev.currentTarget).closest('.job-offer'); 273 | 274 | ev.preventDefault(); 275 | ev.stopImmediatePropagation(); 276 | 277 | window.location.href = 278 | 'mailto:info@ethdev.org?subject=Application for role: ' + 279 | $job.find('.title').text(); 280 | }; 281 | 282 | onClick_toggleMissionStatement = function(ev) { 283 | var $missionStatementContents = $('.mission-statement'); 284 | var isOpen = $missionStatementContents.hasClass('expanded'); 285 | 286 | if (isOpen) { 287 | $missionStatementContents.removeClass('expanded'); 288 | } 289 | else { 290 | $missionStatementContents.addClass('expanded'); 291 | } 292 | 293 | var scrollOffset = scrollPosition($('#mission')); 294 | $('.page-content').clearQueue().animate({scrollTop: scrollOffset}); 295 | }; 296 | 297 | onClick_sectionTab = function(ev) { 298 | $('.page-content') 299 | .clearQueue() 300 | .animate({ 301 | scrollTop: $(this).closest('section').next().get(0).offsetTop 302 | }); 303 | }; 304 | 305 | onSubmit_contactForm = function(ev) { 306 | var data = {}; 307 | 308 | $(ev.target) 309 | .serializeArray() 310 | .forEach(function(x) { data[x.name] = x.value; }); 311 | 312 | ev.preventDefault(); 313 | 314 | var $sendBtn = $('#contact').find("button[type=submit]"), 315 | btnText = $sendBtn.text(); 316 | 317 | $sendBtn.text("Thank you!").prop("disabled", true); 318 | 319 | $.post('/ajax/contact', data).promise() 320 | .then(function() { 321 | setTimeout(function(){ 322 | $sendBtn.text(btnText); 323 | $sendBtn.prop("disabled", false); 324 | },2000); 325 | }, function() { 326 | //oops 327 | }); 328 | }; 329 | 330 | }(this); 331 | -------------------------------------------------------------------------------- /public/js/lib/packery-mode.pkgd.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Packery layout mode PACKAGED v0.1.0 3 | * sub-classes Packery 4 | * http://packery.metafizzy.co 5 | */ 6 | 7 | !function(a){function b(a){return new RegExp("(^|\\s+)"+a+"(\\s+|$)")}function c(a,b){var c=d(a,b)?f:e;c(a,b)}var d,e,f;"classList"in document.documentElement?(d=function(a,b){return a.classList.contains(b)},e=function(a,b){a.classList.add(b)},f=function(a,b){a.classList.remove(b)}):(d=function(a,c){return b(c).test(a.className)},e=function(a,b){d(a,b)||(a.className=a.className+" "+b)},f=function(a,c){a.className=a.className.replace(b(c)," ")});var g={hasClass:d,addClass:e,removeClass:f,toggleClass:c,has:d,add:e,remove:f,toggle:c};"function"==typeof define&&define.amd?define("classie/classie",g):"object"==typeof exports?module.exports=g:a.classie=g}(window),function(a){function b(){function a(b){for(var c in a.defaults)this[c]=a.defaults[c];for(c in b)this[c]=b[c]}return c.Rect=a,a.defaults={x:0,y:0,width:0,height:0},a.prototype.contains=function(a){var b=a.width||0,c=a.height||0;return this.x<=a.x&&this.y<=a.y&&this.x+this.width>=a.x+b&&this.y+this.height>=a.y+c},a.prototype.overlaps=function(a){var b=this.x+this.width,c=this.y+this.height,d=a.x+a.width,e=a.y+a.height;return this.xa.x&&this.ya.y},a.prototype.getMaximalFreeRects=function(b){if(!this.overlaps(b))return!1;var c,d=[],e=this.x+this.width,f=this.y+this.height,g=b.x+b.width,h=b.y+b.height;return this.yg&&(c=new a({x:g,y:this.y,width:e-g,height:this.height}),d.push(c)),f>h&&(c=new a({x:this.x,y:h,width:this.width,height:f-h}),d.push(c)),this.x=a.width&&this.height>=a.height},a}var c=a.Packery=function(){};"function"==typeof define&&define.amd?define("packery/js/rect",b):(a.Packery=a.Packery||{},a.Packery.Rect=b())}(window),function(a){function b(a){function b(a,b,c){this.width=a||0,this.height=b||0,this.sortDirection=c||"downwardLeftToRight",this.reset()}b.prototype.reset=function(){this.spaces=[],this.newSpaces=[];var b=new a({x:0,y:0,width:this.width,height:this.height});this.spaces.push(b),this.sorter=c[this.sortDirection]||c.downwardLeftToRight},b.prototype.pack=function(a){for(var b=0,c=this.spaces.length;c>b;b++){var d=this.spaces[b];if(d.canFit(a)){this.placeInSpace(a,d);break}}},b.prototype.placeInSpace=function(a,b){a.x=b.x,a.y=b.y,this.placed(a)},b.prototype.placed=function(a){for(var c=[],d=0,e=this.spaces.length;e>d;d++){var f=this.spaces[d],g=f.getMaximalFreeRects(a);g?c.push.apply(c,g):c.push(f)}this.spaces=c,b.mergeRects(this.spaces),this.spaces.sort(this.sorter)},b.mergeRects=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];if(d){var e=a.slice(0);e.splice(b,1);for(var f=0,g=0,h=e.length;h>g;g++){var i=e[g],j=b>g?0:1;d.contains(i)&&(a.splice(g+j-f,1),f++)}}}return a};var c={downwardLeftToRight:function(a,b){return a.y-b.y||a.x-b.x},rightwardTopToBottom:function(a,b){return a.x-b.x||a.y-b.y}};return b}if("function"==typeof define&&define.amd)define("packery/js/packer",["./rect"],b);else{var c=a.Packery=a.Packery||{};c.Packer=b(c.Rect)}}(window),function(a){function b(a,b,c){var d=a("transform"),e=function(){b.Item.apply(this,arguments)};e.prototype=new b.Item;var f=e.prototype._create;return e.prototype._create=function(){f.call(this),this.rect=new c,this.placeRect=new c},e.prototype.dragStart=function(){this.getPosition(),this.removeTransitionStyles(),this.isTransitioning&&d&&(this.element.style[d]="none"),this.getSize(),this.isPlacing=!0,this.needsPositioning=!1,this.positionPlaceRect(this.position.x,this.position.y),this.isTransitioning=!1,this.didDrag=!1},e.prototype.dragMove=function(a,b){this.didDrag=!0;var c=this.layout.size;a-=c.paddingLeft,b-=c.paddingTop,this.positionPlaceRect(a,b)},e.prototype.dragStop=function(){this.getPosition();var a=this.position.x!==this.placeRect.x,b=this.position.y!==this.placeRect.y;this.needsPositioning=a||b,this.didDrag=!1},e.prototype.positionPlaceRect=function(a,b,c){this.placeRect.x=this.getPlaceRectCoord(a,!0),this.placeRect.y=this.getPlaceRectCoord(b,!1,c)},e.prototype.getPlaceRectCoord=function(a,b,c){var d=b?"Width":"Height",e=this.size["outer"+d],f=this.layout[b?"columnWidth":"rowHeight"],g=this.layout.size["inner"+d];b||(g=Math.max(g,this.layout.maxY),this.layout.rowHeight||(g-=this.layout.gutter));var h;if(f){f+=this.layout.gutter,g+=b?this.layout.gutter:0,a=Math.round(a/f);var i;i=this.layout.options.isHorizontal?b?"ceil":"floor":b?"floor":"ceil";var j=Math[i](g/f);j-=Math.ceil(e/f),h=j}else h=g-e;return a=c?a:Math.min(a,h),a*=f||1,Math.max(0,a)},e.prototype.copyPlaceRectPosition=function(){this.rect.x=this.placeRect.x,this.rect.y=this.placeRect.y},e}"function"==typeof define&&define.amd?define("packery/js/item",["get-style-property/get-style-property","outlayer/outlayer","./rect"],b):a.Packery.Item=b(a.getStyleProperty,a.Outlayer,a.Packery.Rect)}(window),function(a){function b(a,b,c,d,e,f){function g(a,b){return a.position.y-b.position.y||a.position.x-b.position.x}function h(a,b){return a.position.x-b.position.x||a.position.y-b.position.y}var i=c.create("packery");return i.Item=f,i.prototype._create=function(){c.prototype._create.call(this),this.packer=new e,this.stamp(this.options.stamped);var a=this;this.handleDraggabilly={dragStart:function(b){a.itemDragStart(b.element)},dragMove:function(b){a.itemDragMove(b.element,b.position.x,b.position.y)},dragEnd:function(b){a.itemDragEnd(b.element)}},this.handleUIDraggable={start:function(b){a.itemDragStart(b.currentTarget)},drag:function(b,c){a.itemDragMove(b.currentTarget,c.position.left,c.position.top)},stop:function(b){a.itemDragEnd(b.currentTarget)}}},i.prototype._resetLayout=function(){this.getSize(),this._getMeasurements();var a=this.packer;this.options.isHorizontal?(a.width=Number.POSITIVE_INFINITY,a.height=this.size.innerHeight+this.gutter,a.sortDirection="rightwardTopToBottom"):(a.width=this.size.innerWidth+this.gutter,a.height=Number.POSITIVE_INFINITY,a.sortDirection="downwardLeftToRight"),a.reset(),this.maxY=0,this.maxX=0},i.prototype._getMeasurements=function(){this._getMeasurement("columnWidth","width"),this._getMeasurement("rowHeight","height"),this._getMeasurement("gutter","width")},i.prototype._getItemLayoutPosition=function(a){return this._packItem(a),a.rect},i.prototype._packItem=function(a){this._setRectSize(a.element,a.rect),this.packer.pack(a.rect),this._setMaxXY(a.rect)},i.prototype._setMaxXY=function(a){this.maxX=Math.max(a.x+a.width,this.maxX),this.maxY=Math.max(a.y+a.height,this.maxY)},i.prototype._setRectSize=function(a,c){var d=b(a),e=d.outerWidth,f=d.outerHeight,g=this.columnWidth+this.gutter,h=this.rowHeight+this.gutter;e=this.columnWidth?Math.ceil(e/g)*g:e+this.gutter,f=this.rowHeight?Math.ceil(f/h)*h:f+this.gutter,c.width=Math.min(e,this.packer.width),c.height=Math.min(f,this.packer.height)},i.prototype._getContainerSize=function(){return this.options.isHorizontal?{width:this.maxX-this.gutter}:{height:this.maxY-this.gutter}},i.prototype._manageStamp=function(a){var b,c=this.getItem(a);if(c&&c.isPlacing)b=c.placeRect;else{var e=this._getElementOffset(a);b=new d({x:this.options.isOriginLeft?e.left:e.right,y:this.options.isOriginTop?e.top:e.bottom})}this._setRectSize(a,b),this.packer.placed(b),this._setMaxXY(b)},i.prototype.sortItemsByPosition=function(){var a=this.options.isHorizontal?h:g;this.items.sort(a)},i.prototype.fit=function(a,b,c){var d=this.getItem(a);d&&(this._getMeasurements(),this.stamp(d.element),d.getSize(),d.isPlacing=!0,b=void 0===b?d.rect.x:b,c=void 0===c?d.rect.y:c,d.positionPlaceRect(b,c,!0),this._bindFitEvents(d),d.moveTo(d.placeRect.x,d.placeRect.y),this.layout(),this.unstamp(d.element),this.sortItemsByPosition(),d.isPlacing=!1,d.copyPlaceRectPosition())},i.prototype._bindFitEvents=function(a){function b(){d++,2===d&&c.emitEvent("fitComplete",[c,a])}var c=this,d=0;a.on("layout",function(){return b(),!0}),this.on("layoutComplete",function(){return b(),!0})},i.prototype.resize=function(){var a=b(this.element),c=this.size&&a,d=this.options.isHorizontal?"innerHeight":"innerWidth";c&&a[d]===this.size[d]||this.layout()},i.prototype.itemDragStart=function(a){this.stamp(a);var b=this.getItem(a);b&&b.dragStart()},i.prototype.itemDragMove=function(a,b,c){function d(){f.layout(),delete f.dragTimeout}var e=this.getItem(a);e&&e.dragMove(b,c);var f=this;this.clearDragTimeout(),this.dragTimeout=setTimeout(d,40)},i.prototype.clearDragTimeout=function(){this.dragTimeout&&clearTimeout(this.dragTimeout)},i.prototype.itemDragEnd=function(b){var c,d=this.getItem(b);if(d&&(c=d.didDrag,d.dragStop()),!d||!c&&!d.needsPositioning)return void this.unstamp(b);a.add(d.element,"is-positioning-post-drag");var e=this._getDragEndLayoutComplete(b,d);d.needsPositioning?(d.on("layout",e),d.moveTo(d.placeRect.x,d.placeRect.y)):d&&d.copyPlaceRectPosition(),this.clearDragTimeout(),this.on("layoutComplete",e),this.layout()},i.prototype._getDragEndLayoutComplete=function(b,c){var d=c&&c.needsPositioning,e=0,f=d?2:1,g=this;return function(){return e++,e!==f?!0:(c&&(a.remove(c.element,"is-positioning-post-drag"),c.isPlacing=!1,c.copyPlaceRectPosition()),g.unstamp(b),g.sortItemsByPosition(),d&&g.emitEvent("dragItemPositioned",[g,c]),!0)}},i.prototype.bindDraggabillyEvents=function(a){a.on("dragStart",this.handleDraggabilly.dragStart),a.on("dragMove",this.handleDraggabilly.dragMove),a.on("dragEnd",this.handleDraggabilly.dragEnd)},i.prototype.bindUIDraggableEvents=function(a){a.on("dragstart",this.handleUIDraggable.start).on("drag",this.handleUIDraggable.drag).on("dragstop",this.handleUIDraggable.stop)},i.Rect=d,i.Packer=e,i}"function"==typeof define&&define.amd?define("packery/js/packery",["classie/classie","get-size/get-size","outlayer/outlayer","./rect","./packer","./item"],b):a.Packery=b(a.classie,a.getSize,a.Outlayer,a.Packery.Rect,a.Packery.Packer,a.Packery.Item)}(window),function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}function c(a,c,d){var e=a.create("packery"),f=e.prototype._getElementOffset,g=e.prototype._getMeasurement;b(e.prototype,c.prototype),e.prototype._getElementOffset=f,e.prototype._getMeasurement=g;var h=e.prototype._resetLayout;e.prototype._resetLayout=function(){this.packer=this.packer||new c.Packer,h.apply(this,arguments)};var i=e.prototype._getItemLayoutPosition;e.prototype._getItemLayoutPosition=function(a){return a.rect=a.rect||new c.Rect,i.call(this,a)};var j=e.prototype._manageStamp;return e.prototype._manageStamp=function(){this.options.isOriginLeft=this.isotope.options.isOriginLeft,this.options.isOriginTop=this.isotope.options.isOriginTop,j.apply(this,arguments)},e.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a,c=this.options.isHorizontal?"innerHeight":"innerWidth";return b&&a[c]!==this.size[c]},e}"function"==typeof define&&define.amd?define(["isotope/js/layout-mode","packery/js/packery","get-size/get-size"],c):c(a.Isotope.LayoutMode,a.Packery,a.getSize)}(window); -------------------------------------------------------------------------------- /public/js/lib/jquery.magnific-popup.min.js: -------------------------------------------------------------------------------- 1 | /*! Magnific Popup - v0.9.9 - 2014-09-06 2 | * http://dimsemenov.com/plugins/magnific-popup/ 3 | * Copyright (c) 2014 Dmitry Semenov; */ 4 | (function(e){var t,n,i,o,r,a,s,l="Close",c="BeforeClose",d="AfterClose",u="BeforeAppend",p="MarkupParse",f="Open",m="Change",g="mfp",h="."+g,v="mfp-ready",C="mfp-removing",y="mfp-prevent-close",w=function(){},b=!!window.jQuery,I=e(window),x=function(e,n){t.ev.on(g+e+h,n)},k=function(t,n,i,o){var r=document.createElement("div");return r.className="mfp-"+t,i&&(r.innerHTML=i),o?n&&n.appendChild(r):(r=e(r),n&&r.appendTo(n)),r},T=function(n,i){t.ev.triggerHandler(g+n,i),t.st.callbacks&&(n=n.charAt(0).toLowerCase()+n.slice(1),t.st.callbacks[n]&&t.st.callbacks[n].apply(t,e.isArray(i)?i:[i]))},E=function(n){return n===s&&t.currTemplate.closeBtn||(t.currTemplate.closeBtn=e(t.st.closeMarkup.replace("%title%",t.st.tClose)),s=n),t.currTemplate.closeBtn},_=function(){e.magnificPopup.instance||(t=new w,t.init(),e.magnificPopup.instance=t)},S=function(){var e=document.createElement("p").style,t=["ms","O","Moz","Webkit"];if(void 0!==e.transition)return!0;for(;t.length;)if(t.pop()+"Transition"in e)return!0;return!1};w.prototype={constructor:w,init:function(){var n=navigator.appVersion;t.isIE7=-1!==n.indexOf("MSIE 7."),t.isIE8=-1!==n.indexOf("MSIE 8."),t.isLowIE=t.isIE7||t.isIE8,t.isAndroid=/android/gi.test(n),t.isIOS=/iphone|ipad|ipod/gi.test(n),t.supportsTransition=S(),t.probablyMobile=t.isAndroid||t.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),o=e(document),t.popupsCache={}},open:function(n){i||(i=e(document.body));var r;if(n.isObj===!1){t.items=n.items.toArray(),t.index=0;var s,l=n.items;for(r=0;l.length>r;r++)if(s=l[r],s.parsed&&(s=s.el[0]),s===n.el[0]){t.index=r;break}}else t.items=e.isArray(n.items)?n.items:[n.items],t.index=n.index||0;if(t.isOpen)return t.updateItemHTML(),void 0;t.types=[],a="",t.ev=n.mainEl&&n.mainEl.length?n.mainEl.eq(0):o,n.key?(t.popupsCache[n.key]||(t.popupsCache[n.key]={}),t.currTemplate=t.popupsCache[n.key]):t.currTemplate={},t.st=e.extend(!0,{},e.magnificPopup.defaults,n),t.fixedContentPos="auto"===t.st.fixedContentPos?!t.probablyMobile:t.st.fixedContentPos,t.st.modal&&(t.st.closeOnContentClick=!1,t.st.closeOnBgClick=!1,t.st.showCloseBtn=!1,t.st.enableEscapeKey=!1),t.bgOverlay||(t.bgOverlay=k("bg").on("click"+h,function(){t.close()}),t.wrap=k("wrap").attr("tabindex",-1).on("click"+h,function(e){t._checkIfClose(e.target)&&t.close()}),t.container=k("container",t.wrap)),t.contentContainer=k("content"),t.st.preloader&&(t.preloader=k("preloader",t.container,t.st.tLoading));var c=e.magnificPopup.modules;for(r=0;c.length>r;r++){var d=c[r];d=d.charAt(0).toUpperCase()+d.slice(1),t["init"+d].call(t)}T("BeforeOpen"),t.st.showCloseBtn&&(t.st.closeBtnInside?(x(p,function(e,t,n,i){n.close_replaceWith=E(i.type)}),a+=" mfp-close-btn-in"):t.wrap.append(E())),t.st.alignTop&&(a+=" mfp-align-top"),t.fixedContentPos?t.wrap.css({overflow:t.st.overflowY,overflowX:"hidden",overflowY:t.st.overflowY}):t.wrap.css({top:I.scrollTop(),position:"absolute"}),(t.st.fixedBgPos===!1||"auto"===t.st.fixedBgPos&&!t.fixedContentPos)&&t.bgOverlay.css({height:o.height(),position:"absolute"}),t.st.enableEscapeKey&&o.on("keyup"+h,function(e){27===e.keyCode&&t.close()}),I.on("resize"+h,function(){t.updateSize()}),t.st.closeOnContentClick||(a+=" mfp-auto-cursor"),a&&t.wrap.addClass(a);var u=t.wH=I.height(),m={};if(t.fixedContentPos&&t._hasScrollBar(u)){var g=t._getScrollbarSize();g&&(m.marginRight=g)}t.fixedContentPos&&(t.isIE7?e("body, html").css("overflow","hidden"):m.overflow="hidden");var C=t.st.mainClass;return t.isIE7&&(C+=" mfp-ie7"),C&&t._addClassToMFP(C),t.updateItemHTML(),T("BuildControls"),e("html").css(m),t.bgOverlay.add(t.wrap).prependTo(t.st.prependTo||i),t._lastFocusedEl=document.activeElement,setTimeout(function(){t.content?(t._addClassToMFP(v),t._setFocus()):t.bgOverlay.addClass(v),o.on("focusin"+h,t._onFocusIn)},16),t.isOpen=!0,t.updateSize(u),T(f),n},close:function(){t.isOpen&&(T(c),t.isOpen=!1,t.st.removalDelay&&!t.isLowIE&&t.supportsTransition?(t._addClassToMFP(C),setTimeout(function(){t._close()},t.st.removalDelay)):t._close())},_close:function(){T(l);var n=C+" "+v+" ";if(t.bgOverlay.detach(),t.wrap.detach(),t.container.empty(),t.st.mainClass&&(n+=t.st.mainClass+" "),t._removeClassFromMFP(n),t.fixedContentPos){var i={marginRight:""};t.isIE7?e("body, html").css("overflow",""):i.overflow="",e("html").css(i)}o.off("keyup"+h+" focusin"+h),t.ev.off(h),t.wrap.attr("class","mfp-wrap").removeAttr("style"),t.bgOverlay.attr("class","mfp-bg"),t.container.attr("class","mfp-container"),!t.st.showCloseBtn||t.st.closeBtnInside&&t.currTemplate[t.currItem.type]!==!0||t.currTemplate.closeBtn&&t.currTemplate.closeBtn.detach(),t._lastFocusedEl&&e(t._lastFocusedEl).focus(),t.currItem=null,t.content=null,t.currTemplate=null,t.prevHeight=0,T(d)},updateSize:function(e){if(t.isIOS){var n=document.documentElement.clientWidth/window.innerWidth,i=window.innerHeight*n;t.wrap.css("height",i),t.wH=i}else t.wH=e||I.height();t.fixedContentPos||t.wrap.css("height",t.wH),T("Resize")},updateItemHTML:function(){var n=t.items[t.index];t.contentContainer.detach(),t.content&&t.content.detach(),n.parsed||(n=t.parseEl(t.index));var i=n.type;if(T("BeforeChange",[t.currItem?t.currItem.type:"",i]),t.currItem=n,!t.currTemplate[i]){var o=t.st[i]?t.st[i].markup:!1;T("FirstMarkupParse",o),t.currTemplate[i]=o?e(o):!0}r&&r!==n.type&&t.container.removeClass("mfp-"+r+"-holder");var a=t["get"+i.charAt(0).toUpperCase()+i.slice(1)](n,t.currTemplate[i]);t.appendContent(a,i),n.preloaded=!0,T(m,n),r=n.type,t.container.prepend(t.contentContainer),T("AfterChange")},appendContent:function(e,n){t.content=e,e?t.st.showCloseBtn&&t.st.closeBtnInside&&t.currTemplate[n]===!0?t.content.find(".mfp-close").length||t.content.append(E()):t.content=e:t.content="",T(u),t.container.addClass("mfp-"+n+"-holder"),t.contentContainer.append(t.content)},parseEl:function(n){var i,o=t.items[n];if(o.tagName?o={el:e(o)}:(i=o.type,o={data:o,src:o.src}),o.el){for(var r=t.types,a=0;r.length>a;a++)if(o.el.hasClass("mfp-"+r[a])){i=r[a];break}o.src=o.el.attr("data-mfp-src"),o.src||(o.src=o.el.attr("href"))}return o.type=i||t.st.type||"inline",o.index=n,o.parsed=!0,t.items[n]=o,T("ElementParse",o),t.items[n]},addGroup:function(e,n){var i=function(i){i.mfpEl=this,t._openClick(i,e,n)};n||(n={});var o="click.magnificPopup";n.mainEl=e,n.items?(n.isObj=!0,e.off(o).on(o,i)):(n.isObj=!1,n.delegate?e.off(o).on(o,n.delegate,i):(n.items=e,e.off(o).on(o,i)))},_openClick:function(n,i,o){var r=void 0!==o.midClick?o.midClick:e.magnificPopup.defaults.midClick;if(r||2!==n.which&&!n.ctrlKey&&!n.metaKey){var a=void 0!==o.disableOn?o.disableOn:e.magnificPopup.defaults.disableOn;if(a)if(e.isFunction(a)){if(!a.call(t))return!0}else if(a>I.width())return!0;n.type&&(n.preventDefault(),t.isOpen&&n.stopPropagation()),o.el=e(n.mfpEl),o.delegate&&(o.items=i.find(o.delegate)),t.open(o)}},updateStatus:function(e,i){if(t.preloader){n!==e&&t.container.removeClass("mfp-s-"+n),i||"loading"!==e||(i=t.st.tLoading);var o={status:e,text:i};T("UpdateStatus",o),e=o.status,i=o.text,t.preloader.html(i),t.preloader.find("a").on("click",function(e){e.stopImmediatePropagation()}),t.container.addClass("mfp-s-"+e),n=e}},_checkIfClose:function(n){if(!e(n).hasClass(y)){var i=t.st.closeOnContentClick,o=t.st.closeOnBgClick;if(i&&o)return!0;if(!t.content||e(n).hasClass("mfp-close")||t.preloader&&n===t.preloader[0])return!0;if(n===t.content[0]||e.contains(t.content[0],n)){if(i)return!0}else if(o&&e.contains(document,n))return!0;return!1}},_addClassToMFP:function(e){t.bgOverlay.addClass(e),t.wrap.addClass(e)},_removeClassFromMFP:function(e){this.bgOverlay.removeClass(e),t.wrap.removeClass(e)},_hasScrollBar:function(e){return(t.isIE7?o.height():document.body.scrollHeight)>(e||I.height())},_setFocus:function(){(t.st.focus?t.content.find(t.st.focus).eq(0):t.wrap).focus()},_onFocusIn:function(n){return n.target===t.wrap[0]||e.contains(t.wrap[0],n.target)?void 0:(t._setFocus(),!1)},_parseMarkup:function(t,n,i){var o;i.data&&(n=e.extend(i.data,n)),T(p,[t,n,i]),e.each(n,function(e,n){if(void 0===n||n===!1)return!0;if(o=e.split("_"),o.length>1){var i=t.find(h+"-"+o[0]);if(i.length>0){var r=o[1];"replaceWith"===r?i[0]!==n[0]&&i.replaceWith(n):"img"===r?i.is("img")?i.attr("src",n):i.replaceWith(''):i.attr(o[1],n)}}else t.find(h+"-"+e).html(n)})},_getScrollbarSize:function(){if(void 0===t.scrollbarSize){var e=document.createElement("div");e.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(e),t.scrollbarSize=e.offsetWidth-e.clientWidth,document.body.removeChild(e)}return t.scrollbarSize}},e.magnificPopup={instance:null,proto:w.prototype,modules:[],open:function(t,n){return _(),t=t?e.extend(!0,{},t):{},t.isObj=!0,t.index=n||0,this.instance.open(t)},close:function(){return e.magnificPopup.instance&&e.magnificPopup.instance.close()},registerModule:function(t,n){n.options&&(e.magnificPopup.defaults[t]=n.options),e.extend(this.proto,n.proto),this.modules.push(t)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'',tClose:"Close (Esc)",tLoading:"Loading..."}},e.fn.magnificPopup=function(n){_();var i=e(this);if("string"==typeof n)if("open"===n){var o,r=b?i.data("magnificPopup"):i[0].magnificPopup,a=parseInt(arguments[1],10)||0;r.items?o=r.items[a]:(o=i,r.delegate&&(o=o.find(r.delegate)),o=o.eq(a)),t._openClick({mfpEl:o},i,r)}else t.isOpen&&t[n].apply(t,Array.prototype.slice.call(arguments,1));else n=e.extend(!0,{},n),b?i.data("magnificPopup",n):i[0].magnificPopup=n,t.addGroup(i,n);return i};var P,O,z,M="inline",B=function(){z&&(O.after(z.addClass(P)).detach(),z=null)};e.magnificPopup.registerModule(M,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){t.types.push(M),x(l+"."+M,function(){B()})},getInline:function(n,i){if(B(),n.src){var o=t.st.inline,r=e(n.src);if(r.length){var a=r[0].parentNode;a&&a.tagName&&(O||(P=o.hiddenClass,O=k(P),P="mfp-"+P),z=r.after(O).detach().removeClass(P)),t.updateStatus("ready")}else t.updateStatus("error",o.tNotFound),r=e("
");return n.inlineElement=r,r}return t.updateStatus("ready"),t._parseMarkup(i,{},n),i}}});var F,H="ajax",L=function(){F&&i.removeClass(F)},A=function(){L(),t.req&&t.req.abort()};e.magnificPopup.registerModule(H,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'The content could not be loaded.'},proto:{initAjax:function(){t.types.push(H),F=t.st.ajax.cursor,x(l+"."+H,A),x("BeforeChange."+H,A)},getAjax:function(n){F&&i.addClass(F),t.updateStatus("loading");var o=e.extend({url:n.src,success:function(i,o,r){var a={data:i,xhr:r};T("ParseAjax",a),t.appendContent(e(a.data),H),n.finished=!0,L(),t._setFocus(),setTimeout(function(){t.wrap.addClass(v)},16),t.updateStatus("ready"),T("AjaxContentAdded")},error:function(){L(),n.finished=n.loadError=!0,t.updateStatus("error",t.st.ajax.tError.replace("%url%",n.src))}},t.st.ajax.settings);return t.req=e.ajax(o),""}}});var j,N=function(n){if(n.data&&void 0!==n.data.title)return n.data.title;var i=t.st.image.titleSrc;if(i){if(e.isFunction(i))return i.call(t,n);if(n.el)return n.el.attr(i)||""}return""};e.magnificPopup.registerModule("image",{options:{markup:'
',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'The image could not be loaded.'},proto:{initImage:function(){var e=t.st.image,n=".image";t.types.push("image"),x(f+n,function(){"image"===t.currItem.type&&e.cursor&&i.addClass(e.cursor)}),x(l+n,function(){e.cursor&&i.removeClass(e.cursor),I.off("resize"+h)}),x("Resize"+n,t.resizeImage),t.isLowIE&&x("AfterChange",t.resizeImage)},resizeImage:function(){var e=t.currItem;if(e&&e.img&&t.st.image.verticalFit){var n=0;t.isLowIE&&(n=parseInt(e.img.css("padding-top"),10)+parseInt(e.img.css("padding-bottom"),10)),e.img.css("max-height",t.wH-n)}},_onImageHasSize:function(e){e.img&&(e.hasSize=!0,j&&clearInterval(j),e.isCheckingImgSize=!1,T("ImageHasSize",e),e.imgHidden&&(t.content&&t.content.removeClass("mfp-loading"),e.imgHidden=!1))},findImageSize:function(e){var n=0,i=e.img[0],o=function(r){j&&clearInterval(j),j=setInterval(function(){return i.naturalWidth>0?(t._onImageHasSize(e),void 0):(n>200&&clearInterval(j),n++,3===n?o(10):40===n?o(50):100===n&&o(500),void 0)},r)};o(1)},getImage:function(n,i){var o=0,r=function(){n&&(n.img[0].complete?(n.img.off(".mfploader"),n===t.currItem&&(t._onImageHasSize(n),t.updateStatus("ready")),n.hasSize=!0,n.loaded=!0,T("ImageLoadComplete")):(o++,200>o?setTimeout(r,100):a()))},a=function(){n&&(n.img.off(".mfploader"),n===t.currItem&&(t._onImageHasSize(n),t.updateStatus("error",s.tError.replace("%url%",n.src))),n.hasSize=!0,n.loaded=!0,n.loadError=!0)},s=t.st.image,l=i.find(".mfp-img");if(l.length){var c=document.createElement("img");c.className="mfp-img",n.img=e(c).on("load.mfploader",r).on("error.mfploader",a),c.src=n.src,l.is("img")&&(n.img=n.img.clone()),c=n.img[0],c.naturalWidth>0?n.hasSize=!0:c.width||(n.hasSize=!1)}return t._parseMarkup(i,{title:N(n),img_replaceWith:n.img},n),t.resizeImage(),n.hasSize?(j&&clearInterval(j),n.loadError?(i.addClass("mfp-loading"),t.updateStatus("error",s.tError.replace("%url%",n.src))):(i.removeClass("mfp-loading"),t.updateStatus("ready")),i):(t.updateStatus("loading"),n.loading=!0,n.hasSize||(n.imgHidden=!0,i.addClass("mfp-loading"),t.findImageSize(n)),i)}}});var W,R=function(){return void 0===W&&(W=void 0!==document.createElement("p").style.MozTransform),W};e.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(e){return e.is("img")?e:e.find("img")}},proto:{initZoom:function(){var e,n=t.st.zoom,i=".zoom";if(n.enabled&&t.supportsTransition){var o,r,a=n.duration,s=function(e){var t=e.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),i="all "+n.duration/1e3+"s "+n.easing,o={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},r="transition";return o["-webkit-"+r]=o["-moz-"+r]=o["-o-"+r]=o[r]=i,t.css(o),t},d=function(){t.content.css("visibility","visible")};x("BuildControls"+i,function(){if(t._allowZoom()){if(clearTimeout(o),t.content.css("visibility","hidden"),e=t._getItemToZoom(),!e)return d(),void 0;r=s(e),r.css(t._getOffset()),t.wrap.append(r),o=setTimeout(function(){r.css(t._getOffset(!0)),o=setTimeout(function(){d(),setTimeout(function(){r.remove(),e=r=null,T("ZoomAnimationEnded")},16)},a)},16)}}),x(c+i,function(){if(t._allowZoom()){if(clearTimeout(o),t.st.removalDelay=a,!e){if(e=t._getItemToZoom(),!e)return;r=s(e)}r.css(t._getOffset(!0)),t.wrap.append(r),t.content.css("visibility","hidden"),setTimeout(function(){r.css(t._getOffset())},16)}}),x(l+i,function(){t._allowZoom()&&(d(),r&&r.remove(),e=null)})}},_allowZoom:function(){return"image"===t.currItem.type},_getItemToZoom:function(){return t.currItem.hasSize?t.currItem.img:!1},_getOffset:function(n){var i;i=n?t.currItem.img:t.st.zoom.opener(t.currItem.el||t.currItem);var o=i.offset(),r=parseInt(i.css("padding-top"),10),a=parseInt(i.css("padding-bottom"),10);o.top-=e(window).scrollTop()-r;var s={width:i.width(),height:(b?i.innerHeight():i[0].offsetHeight)-a-r};return R()?s["-moz-transform"]=s.transform="translate("+o.left+"px,"+o.top+"px)":(s.left=o.left,s.top=o.top),s}}});var Z="iframe",q="//about:blank",D=function(e){if(t.currTemplate[Z]){var n=t.currTemplate[Z].find("iframe");n.length&&(e||(n[0].src=q),t.isIE8&&n.css("display",e?"block":"none"))}};e.magnificPopup.registerModule(Z,{options:{markup:'
',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){t.types.push(Z),x("BeforeChange",function(e,t,n){t!==n&&(t===Z?D():n===Z&&D(!0))}),x(l+"."+Z,function(){D()})},getIframe:function(n,i){var o=n.src,r=t.st.iframe;e.each(r.patterns,function(){return o.indexOf(this.index)>-1?(this.id&&(o="string"==typeof this.id?o.substr(o.lastIndexOf(this.id)+this.id.length,o.length):this.id.call(this,o)),o=this.src.replace("%id%",o),!1):void 0});var a={};return r.srcAction&&(a[r.srcAction]=o),t._parseMarkup(i,a,n),t.updateStatus("ready"),i}}});var K=function(e){var n=t.items.length;return e>n-1?e-n:0>e?n+e:e},Y=function(e,t,n){return e.replace(/%curr%/gi,t+1).replace(/%total%/gi,n)};e.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var n=t.st.gallery,i=".mfp-gallery",r=Boolean(e.fn.mfpFastClick);return t.direction=!0,n&&n.enabled?(a+=" mfp-gallery",x(f+i,function(){n.navigateByImgClick&&t.wrap.on("click"+i,".mfp-img",function(){return t.items.length>1?(t.next(),!1):void 0}),o.on("keydown"+i,function(e){37===e.keyCode?t.prev():39===e.keyCode&&t.next()})}),x("UpdateStatus"+i,function(e,n){n.text&&(n.text=Y(n.text,t.currItem.index,t.items.length))}),x(p+i,function(e,i,o,r){var a=t.items.length;o.counter=a>1?Y(n.tCounter,r.index,a):""}),x("BuildControls"+i,function(){if(t.items.length>1&&n.arrows&&!t.arrowLeft){var i=n.arrowMarkup,o=t.arrowLeft=e(i.replace(/%title%/gi,n.tPrev).replace(/%dir%/gi,"left")).addClass(y),a=t.arrowRight=e(i.replace(/%title%/gi,n.tNext).replace(/%dir%/gi,"right")).addClass(y),s=r?"mfpFastClick":"click";o[s](function(){t.prev()}),a[s](function(){t.next()}),t.isIE7&&(k("b",o[0],!1,!0),k("a",o[0],!1,!0),k("b",a[0],!1,!0),k("a",a[0],!1,!0)),t.container.append(o.add(a))}}),x(m+i,function(){t._preloadTimeout&&clearTimeout(t._preloadTimeout),t._preloadTimeout=setTimeout(function(){t.preloadNearbyImages(),t._preloadTimeout=null},16)}),x(l+i,function(){o.off(i),t.wrap.off("click"+i),t.arrowLeft&&r&&t.arrowLeft.add(t.arrowRight).destroyMfpFastClick(),t.arrowRight=t.arrowLeft=null}),void 0):!1},next:function(){t.direction=!0,t.index=K(t.index+1),t.updateItemHTML()},prev:function(){t.direction=!1,t.index=K(t.index-1),t.updateItemHTML()},goTo:function(e){t.direction=e>=t.index,t.index=e,t.updateItemHTML()},preloadNearbyImages:function(){var e,n=t.st.gallery.preload,i=Math.min(n[0],t.items.length),o=Math.min(n[1],t.items.length);for(e=1;(t.direction?o:i)>=e;e++)t._preloadItem(t.index+e);for(e=1;(t.direction?i:o)>=e;e++)t._preloadItem(t.index-e)},_preloadItem:function(n){if(n=K(n),!t.items[n].preloaded){var i=t.items[n];i.parsed||(i=t.parseEl(n)),T("LazyLoad",i),"image"===i.type&&(i.img=e('').on("load.mfploader",function(){i.hasSize=!0}).on("error.mfploader",function(){i.hasSize=!0,i.loadError=!0,T("LazyLoadError",i)}).attr("src",i.src)),i.preloaded=!0}}}});var U="retina";e.magnificPopup.registerModule(U,{options:{replaceSrc:function(e){return e.src.replace(/\.\w+$/,function(e){return"@2x"+e})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var e=t.st.retina,n=e.ratio;n=isNaN(n)?n():n,n>1&&(x("ImageHasSize."+U,function(e,t){t.img.css({"max-width":t.img[0].naturalWidth/n,width:"100%"})}),x("ElementParse."+U,function(t,i){i.src=e.replaceSrc(i,n)}))}}}}),function(){var t=1e3,n="ontouchstart"in window,i=function(){I.off("touchmove"+r+" touchend"+r)},o="mfpFastClick",r="."+o;e.fn.mfpFastClick=function(o){return e(this).each(function(){var a,s=e(this);if(n){var l,c,d,u,p,f;s.on("touchstart"+r,function(e){u=!1,f=1,p=e.originalEvent?e.originalEvent.touches[0]:e.touches[0],c=p.clientX,d=p.clientY,I.on("touchmove"+r,function(e){p=e.originalEvent?e.originalEvent.touches:e.touches,f=p.length,p=p[0],(Math.abs(p.clientX-c)>10||Math.abs(p.clientY-d)>10)&&(u=!0,i())}).on("touchend"+r,function(e){i(),u||f>1||(a=!0,e.preventDefault(),clearTimeout(l),l=setTimeout(function(){a=!1},t),o())})})}s.on("click"+r,function(){a||o()})})},e.fn.destroyMfpFastClick=function(){e(this).off("touchstart"+r+" click"+r),n&&I.off("touchmove"+r+" touchend"+r)}}(),_()})(window.jQuery||window.Zepto); --------------------------------------------------------------------------------