Commit 544a1a55 authored by John's avatar John

😎

parents
Pipeline #14004004 failed with stage
in 1 minute and 55 seconds
{
"directory": ".tmp/lib"
}
\ No newline at end of file
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
.sass-cache
.tmp
.publish
dist
_sandbox
.DS_Store
node_modules
image: node:8.9.1
pages:
stage: deploy
script:
- npm install
- mkdir .public
- gulp
- cp -r dist/* .public
- mv .public public
artifacts:
paths:
- public
only:
- master
\ No newline at end of file
{
"preset": "google",
"validateLineBreaks": "LF",
"validateIndentation": 2,
"excludeFiles": ["node_modules/**"]
}
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"newcap": true,
"noarg": true,
"quotmark": "single",
"undef": true,
"unused": "vars",
"strict": true
}
This diff is collapsed.
# jawnnypoo.com
My [site](http://jawnnypoo.com)
Forked from https://github.com/romannurik/roman.nurik.net
# Run
```
gulp serve
```
# Deploy
```
npm install
./deploy.sh
# or
deploy.bat
```
# Reminders
Extract video from device via Logcat within Android Studio
Extract still image from video via VLC: Video -> Take Snapshot
\ No newline at end of file
This diff is collapsed.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="theme-color" content="#ffffff">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="{% block description %}Hey there, I'm John. I love all things development, especially making cool apps. I got my start in game programming, and I love making games and apps with my wife.{% endblock %}">
<title>{% if title %}{{ title }} &mdash; {% endif %}John Carlson</title>
<meta name="mobile-web-app-capable" content="yes">
<link rel="icon" sizes="192x192" href="chrome-touch-icon-192x192.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="John Carlson">
<!-- Chrome for Android theme color -->
<meta name="theme-color" content="#E64A19">
{% block css %}
{% endblock %}
<script src="https://use.typekit.net/kpt3ulr.js"></script>
<script>try{Typekit.load(/*{ async: true }*/);}catch(e){}</script>
</head>
<body>
{% block page-body %}
{% endblock %}
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/lib/fastclick/lib/fastclick.js"></script>
{% block js %}
{% endblock %}
</body>
</html>
{% extends '_base.html' %}
{% block page-body %}
<nav class="top-bar">
<div class="top-bar-content">
<a class="home-link" href="/"><span>John Carlson - @Jawnnypoo</span></a>
</div>
</nav>
<div class="page-content">
{% block subpage-body %}
{% endblock %}
</div>
{% endblock %}
\ No newline at end of file
{% extends '_base.html' %}
{% block css %}
<link rel="stylesheet" href="/styles/landing.css">
{% endblock %}
{% block js %}
<script src="/scripts/landing.js"></script>
{% endblock %}
{% block page-body %}
<div class="top"></div>
<div class="content-container">
<div class="content">
<div class="avatar"></div>
<p>Hey there, I'm John, aka Jawn, aka Jawnnypoo.</p>
<p>Fortunately, I get to do what I love. From creating open source libraries to making apps with my wife to learning something new, I care about craft, industry, and community.</p>
<p>I'm a serious developer trying not to take life too seriously. See some of my work in my <a href="/portfolio/">portfolio</a>.</p>
<!-- icons thanks to https://github.com/shalinguyen/socialicious -->
<div class="icons">
<a rel="me" href="https://github.com/Jawnnypoo" title="GitHub" class="github"></a>
<a rel="me" href="https://twitter.com/Jawnnypoo" title="Twitter" class="twitter"></a>
<a rel="me" href="" title="Email" class="email obfuscated" data-email="jawnnypoo gmail com"></a>
</div>
</div>
</div>
<div class="bottom"></div>
{% endblock %}
\ No newline at end of file
---
title: Portfolio
---
{% extends '../_subpage.html' %}
{% block css %}
<link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="/styles/portfolio.css" />
{% endblock %}
{% block js %}
<script src="/lib/hammerjs/hammer.min.js"></script>
<script src="/scripts/portfolio.js"></script>
{% endblock %}
{% block subpage-body %}
{% parent %}
<header>
<h1>{{ title }}</h1>
<div class="intro">
{% markdown %}
Here is a sample of some of the work I have done, covering work as well as side projects. I've also done tons of work as an open sourcerer, which is up on [GitHub](https://github.com/Commit451).
{% endmarkdown %}
</div>
</header>
<main>
{% for project in projects %}
<section class="project {{ project.extra_classes }}">
<div class="info">
<h2>{{ project.name }}</h2>
<p class="date">{{ project.date }}</p>
{{ project.description | markdown }}
{% if project.actions %}
<div class="actions">
{% for action in project.actions %}
<a href="{{ action.url }}">{{ action.caption }}</a>
{% endfor %}
</div>
{% endif %}
</div>
<div class="pages">
{% for page in project.pages %}
<div class="page {{ page.extra_classes }} {% if page.video %}video{% endif %} {% if page.image %}image{% endif %}" style="background-color: {{ page.color | material_color }} {% if project.pager_height %}; height:{{project.pager_height}}px{% endif %}">
<div tabindex="0" class="media loader-parent" {% if page.color2 %} style="color:{{ page.color2 | material_color }}"{% endif %}>
<div
{% if page.offset_media %}style="transform: translate({{ page.offset_media }});"{% endif %}
{% if page.device_frame %}class="device-frame device-{{ page.device_frame }}"{% endif %}>
{% if page.image %}
<!-- <div class="media image" style="background-image: url(/media/{{ page.image }});"></div> -->
<img src="/media/{{ page.image }}">
{% endif %}
{% if page.video %}
<video loop preload="none">
<source src="/media/{{ page.video }}.mp4" type="video/mp4">
<source src="/media/{{ page.video }}.webm" type="video/webm">
</video>
<img class="thumb" src="/media/{{ page.video }}-thumb.png">
{% endif %}
</div>
<svg class="loading-spinner" width="64" height="64" viewbox="0 0 64 64">
<circle cx="32" cy="32" r="20" fill="none" stroke-width="6" stroke-miterlimit="10" stroke="#ccc" />
</svg>
</div>
{% if page.caption %}
<div class="caption">
{{ page.caption | markdown }}
</div>
{% endif %}
</div>
{% endfor %}
</div>
</section>
{% endfor %}
</main>
<footer>
{% markdown %}
Forked from Roman Nurik's [awesome site](https://github.com/romannurik/roman.nurik.net).
[See the source](https://github.com/Jawnnypoo/jawnnypoo.com)
{% endmarkdown %}
</footer>
{% endblock %}
\ No newline at end of file
<svg width="1440" height="44" viewBox="0 0 1440 44" xmlns="http://www.w3.org/2000/svg">
<path d="M0 16.01C0 7.167 7.173 0 16.002 0h1407.996C1432.835 0 1440 7.167 1440 16.01V44H0V16.01zM28 30c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm32 0c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm32 0c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8z" fill-opacity=".2" fill="#000" fill-rule="evenodd"/>
</svg>
<svg width="1440" height="44" viewBox="0 0 1440 44" xmlns="http://www.w3.org/2000/svg">
<path d="M0 16.01C0 7.167 7.173 0 16.002 0h1407.996C1432.835 0 1440 7.167 1440 16.01V44H0V16.01zM28 30c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm32 0c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm32 0c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8z" fill-opacity=".8" fill="#FFF" fill-rule="evenodd"/>
</svg>
<svg width="1776" height="1049" viewBox="0 0 1776 1049" xmlns="http://www.w3.org/2000/svg">
<path d="M1587.49 964.59c0 8.95-7.32 16.27-16.27 16.27H208.26c-8.95 0-16.26-7.32-16.26-16.27V16.27C192 7.32 199.32 0 208.26 0h1362.96c8.95 0 16.27 7.32 16.27 16.27v948.32zM1108.354 988h667.366v48c0 2.99-2.4 5.91-5.32 6.49l-25.51 5.1c-2.92.58-7.76 1.06-10.74 1.06H32.53c-2.98 0-7.78-.63-10.66-1.4l-16.63-4.43c-2.88-.77-5.24-3.84-5.24-6.82v-48h666.906l17.394 27.33c3.72 5.88 12.46 10.69 19.42 10.69h367.82c6.96 0 15.7-4.81 19.42-10.69l17.394-27.33z" fill-opacity=".2" fill-rule="evenodd"/>
</svg>
<svg width="1776" height="1049" viewBox="0 0 1776 1049" xmlns="http://www.w3.org/2000/svg">
<path d="M1587.49 964.59c0 8.95-7.32 16.27-16.27 16.27H208.26c-8.95 0-16.26-7.32-16.26-16.27V16.27C192 7.32 199.32 0 208.26 0h1362.96c8.95 0 16.27 7.32 16.27 16.27v948.32zM1108.354 988h667.366v48c0 2.99-2.4 5.91-5.32 6.49l-25.51 5.1c-2.92.58-7.76 1.06-10.74 1.06H32.53c-2.98 0-7.78-.63-10.66-1.4l-16.63-4.43c-2.88-.77-5.24-3.84-5.24-6.82v-48h666.906l17.394 27.33c3.72 5.88 12.46 10.69 19.42 10.69h367.82c6.96 0 15.7-4.81 19.42-10.69l17.394-27.33z" fill-opacity=".8" fill="#FFF" fill-rule="evenodd"/>
</svg>
<svg width="396" height="804" viewBox="0 0 396 804" xmlns="http://www.w3.org/2000/svg">
<path d="M396 46c-.003.42.697-21.685-19-31C354.698 5.024 245.1 0 198 0 150.703 0 41.205 5.024 19 15-.894 24.315.006 46.42 0 46v712c.006-.42-.894 21.685 19 31 22.205 9.976 131.803 15 179 15 47.2 0 156.698-5.024 179-15 19.697-9.315 18.997-31.42 19-31V46zm-198 4c5.3 0 10-4.7 10-10 0-6.3-4.7-11-10-11-6.3 0-11 4.7-11 11 0 5.3 4.7 10 11 10z" fill-opacity=".2" fill="#000" fill-rule="evenodd"/>
</svg>
<svg width="396" height="804" viewBox="0 0 396 804" xmlns="http://www.w3.org/2000/svg">
<path d="M396 46c-.003.42.697-21.685-19-31C354.698 5.024 245.1 0 198 0 150.703 0 41.205 5.024 19 15-.894 24.315.006 46.42 0 46v712c.006-.42-.894 21.685 19 31 22.205 9.976 131.803 15 179 15 47.2 0 156.698-5.024 179-15 19.697-9.315 18.997-31.42 19-31V46zm-198 4c5.3 0 10-4.7 10-10 0-6.3-4.7-11-10-11-6.3 0-11 4.7-11 11 0 5.3 4.7 10 11 10z" fill-opacity=".8" fill="#FFF" fill-rule="evenodd"/>
</svg>
<svg width="396" height="680" viewBox="0 0 396 680" xmlns="http://www.w3.org/2000/svg">
<path d="M286 162.58L268.47 9.935C267.84 4.45 262.854 0 257.33 0H138.67c-5.524 0-10.51 4.448-11.14 9.934L110 162.58C44.804 194.98 0 262.26 0 340c0 77.742 44.804 145.02 110 177.42l17.53 152.646c.63 5.486 5.616 9.934 11.14 9.934h118.66c5.523 0 10.51-4.45 11.14-9.934L286 517.42c65.196-32.4 110-99.678 110-177.42 0-77.742-44.804-145.02-110-177.42z" fill-opacity=".2" fill-rule="evenodd"/>
</svg>
<svg width="396" height="680" viewBox="0 0 396 680" xmlns="http://www.w3.org/2000/svg">
<path d="M286 162.58L268.47 9.935C267.84 4.45 262.854 0 257.33 0H138.67c-5.524 0-10.51 4.448-11.14 9.934L110 162.58C44.804 194.98 0 262.26 0 340c0 77.742 44.804 145.02 110 177.42l17.53 152.646c.63 5.486 5.616 9.934 11.14 9.934h118.66c5.523 0 10.51-4.45 11.14-9.934L286 517.42c65.196-32.4 110-99.678 110-177.42 0-77.742-44.804-145.02-110-177.42z" fill-opacity=".8" fill="#FFF" fill-rule="evenodd"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -38 100 100"><path fill="#FFF" d="M90-28H10C4.5-28 0-23.5 0-18v60c0 5.5 4.5 10 10 10h80c5.5 0 10-4.5 10-10v-60c0-5.5-4.5-10-10-10zm0 20L50 17 10-8v-10L50 7l40-25v10z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M65.8 98.7c-2.5.5-3.4-1.1-3.4-2.4 0-1.6.1-7 .1-13.7 0-4.7-1.6-7.7-3.4-9.3 11.1-1.2 22.8-5.5 22.8-24.7 0-5.5-1.9-9.9-5.1-13.4.5-1.3 2.2-6.3-.5-13.2 0 0-4.2-1.3-13.7 5.1-4-1.1-8.3-1.7-12.5-1.7-4.2 0-8.5.6-12.5 1.7-9.7-6.5-13.9-5.1-13.9-5.1-2.7 6.9-1 12-.5 13.2-3.2 3.5-5.2 8-5.2 13.4C18 67.8 29.7 72 40.8 73.3c-1.4 1.2-2.7 3.5-3.2 6.7-2.9 1.3-10.1 3.5-14.5-4.2 0 0-2.6-4.8-7.7-5.2 0 0-4.9-.1-.3 3 0 0 3.3 1.5 5.6 7.3 0 0 2.9 8.9 16.8 5.9 0 4.2.1 8.1.1 9.3 0 1.3-.9 2.9-3.4 2.4C14.3 92.1 0 73.3 0 51.2c0-27.6 22.4-50 50-50s50 22.4 50 50c0 22.1-14.3 40.9-34.2 47.5z" fill="#fff"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M100 19c-3.7 1.6-7.6 2.7-11.8 3.2 4.2-2.5 7.5-6.6 9-11.4-4 2.4-8.4 4.1-13 5-3.7-4-9.1-6.5-15-6.5-11.3 0-20.5 9.2-20.5 20.5 0 1.6.2 3.2.5 4.7-17.1-.9-32.2-9-42.3-21.4-1.8 3-2.8 6.6-2.8 10.3 0 7.1 3.6 13.4 9.1 17.1-3.4-.1-6.5-1-9.3-2.6v.3c0 9.9 7.1 18.2 16.5 20.1-1.7.5-3.5.7-5.4.7-1.3 0-2.6-.1-3.9-.4 2.6 8.1 10.2 14.1 19.2 14.2-7 5.5-15.9 8.8-25.5 8.8-1.7 0-3.3-.1-4.9-.3 9.1 5.8 19.9 9.2 31.4 9.2 37.7 0 58.4-31.3 58.4-58.4 0-.9 0-1.8-.1-2.7 4.2-2.7 7.7-6.3 10.4-10.4z" fill="#fff"/></svg>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
# www.robotstxt.org/
# Allow crawling of all content
User-agent: *
Disallow:
require('./_jquery-wheelswipe');
(function($) {
$.fn.carousel = function() {
var args = arguments;
var returnValue;
$(this).each(function() {
returnValue = _carousel.apply(this, args);
});
return returnValue;
};
// Make a carousel or send carousel command to a single carousel
function _carousel(opts) {
var carouselNode = this;
if (typeof opts === 'string') {
var action = opts;
var carouselObj = carouselNode._carousel;
switch (action) {
case 'getPage':
return carouselObj.currentPage;
case 'setPage':
carouselObj.snapToPage(arguments[1], true);
return;
}
return;
}
var carouselObj = new Carousel(this, opts);
carouselObj.build();
carouselNode._carousel = carouselObj;
}
// Carousel class
function Carousel(node, opts) {
this.node = node;
this.$carousel = $(node);
this.opts = $.extend({}, opts || {});
this.opts.loadPage = this.opts.loadPage || function(){};
}
Carousel.prototype.build = function() {
var me = this;
this.$pages = this.$carousel.find('.page');
this.$pageScroller = $('<div>')
.addClass('page-scroll')
.append(this.$pages)
.appendTo(this.$carousel);
this.currentPage = -1;
this.loadedPages = {};
this.panning = false;
this.scrollX = 0;
this.numPages = this.$pages.length;
// cancel some default behaviors, regardless if there are pages or not
this.preventDefaultBrowserBehaviors();
$(window).resize(function() {
me.relayout();
});
if (this.numPages <= 1) {
this.relayout();
return;
}
// more than one page
this.$carousel.addClass('pannable');
this.buildPageNavigation();
this.relayout();
this.scrollTo(0, false, false);
this.setupSwipe();
};
Carousel.prototype.setupSwipe = function() {
var me = this;
this.$carousel.wheelswipe(function(direction) {
me.snapToPage(me.currentPage + direction, true);
});
// set up hammer JS
var lastDeltaX = 0;
var pageAtPanStart = -1;
var swiped = false;
var hammer = new Hammer(this.$carousel.get(0), {
dragLockToAxis: true
});
hammer.on('panend pan swipe', function(ev) {
// disable browser scrolling
ev.preventDefault();
ev.srcEvent.preventDefault();
var right = ev.deltaX < 0;
switch (ev.type) {
case 'pan':
if (!swiped) {
var deltaX = (ev.deltaX - lastDeltaX);
me.panning = true;
if (pageAtPanStart < 0) {
pageAtPanStart = me.currentPage;
}
me.$carousel.addClass('panning');
me.scrollTo(me.scrollX - deltaX);
lastDeltaX = ev.deltaX;
}
break;
case 'swipe':
swiped = true;
lastDeltaX = 0;
right = (ev.direction & Hammer.DIRECTION_RIGHT) == 0;
me.snapToPage(pageAtPanStart + (right ? 1 : -1), true);
setTimeout(function() {
me.panning = false;
pageAtPanStart = -1;
me.$carousel.removeClass('panning');
}, 0);
ev.srcEvent.stopPropagation();
break;
case 'panend':
if (!swiped) {
lastDeltaX = 0;
me.snapToPage(me.currentPage, true);
setTimeout(function() {
me.panning = false;
pageAtPanStart = -1;
me.$carousel.removeClass('panning');
}, 0);
}
swiped = false;
break;
}
});
};
Carousel.prototype.preventDefaultBrowserBehaviors = function() {
var me = this;
this.$carousel
.on('dragstart', function(ev) {
ev.preventDefault();
})
.on('click', function(ev) {
if (me.panning) {
ev.preventDefault();
ev.stopPropagation();
}
})
.on('wheel', function(e) {
if (Math.abs(e.originalEvent.deltaX)) {
e.preventDefault();
}
})
// prevent tab-focus from scrolling the carousel weirdly
.on('focusin', function(ev) {
var $page = $(ev.target).parents('.page');
if ($page.length) {
setTimeout(function() {
me.$carousel.scrollLeft(0);
me.snapToPage($page.index(), true);
}, 0);
}
});
};
Carousel.prototype.buildPageNavigation = function() {
var me = this;
// create edge clickers
this.$edgeClickerPrev = $('<div>')
.addClass('edge-clicker prev')
.appendTo(this.$carousel)
.click(function() {
me.snapToPage(me.currentPage - 1, true);
});
this.$edgeClickerNext = $('<div>')
.addClass('edge-clicker next')
.appendTo(this.$carousel)
.click(function() {
me.snapToPage(me.currentPage + 1, true);
});
this.$pageDots = $('<div>').addClass('page-dots').appendTo(this.$carousel);
var pageDotClick_ = function() {
me.snapToPage($(this).index(), true);
};
for (var i = 0; i < this.numPages; i++) {
this.$pageDots.append($('<div>').addClass('page-dot').click(pageDotClick_));
}
};
Carousel.prototype.loadPageByIndex = function(pageIndex) {
if (pageIndex < 0 || pageIndex >= this.numPages || pageIndex in this.loadedPages) {
return;
}
this.loadedPages[pageIndex] = true;
this.opts.loadPage(this.$pages.eq(pageIndex));
};
Carousel.prototype.scrollTo = function(x, animated, loadPages) {
if (loadPages === undefined) {
loadPages = true;
}
if (animated === undefined) {
animated = false;
}
this.scrollX = Math.max(0, Math.min((this.pageWidth + this.pageSpacing) * (this.numPages - 1), x));
this.$pageScroller
.toggleClass('animate-scroll', animated)
.css('transform', 'translate3d(' + (-this.scrollX) + 'px,0,0)');
var newCurrentPage = Math.round(this.scrollX / this.pageWidth);
if (this.currentPage != newCurrentPage) {
this.currentPage = newCurrentPage;
if (loadPages) {
this.loadPageByIndex(this.currentPage - 1);
this.loadPageByIndex(this.currentPage);
this.loadPageByIndex(this.currentPage + 1);
}
var me = this;
if (this.$pageDots) {
this.$pageDots.find('.page-dot').each(function(index) {
$(this).toggleClass('active', index == me.currentPage);
});
}
this.$carousel.trigger('carouselpagechanged');
}
};
Carousel.prototype.snapToPage = function(pageIndex, animated) {
this.scrollTo(pageIndex * (this.pageWidth + this.pageSpacing), animated);
};
Carousel.prototype.relayout = function() {
this.pagePeek = (window.screen.width < 480) ? 16 : 32;
this.pageSpacing = 16;