Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["es2015"],
"compact": false,
}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.sass-cache
node_modules
prod.js.map
style.css.map
76 changes: 76 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* A lot of directories are verbose without wildcards, largely a result of having a shared codebase with the backend code.
*
* TODO: Separate tasks for backend app!
*/
module.exports = function (grunt) {

// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

/**
* Converts our Sass files to CSS.
*/
sass: {
compile: {
options: {
style: 'nested'
},
files: {
'public/css/style.css': 'style.scss'
}
}
},


/**
* Watches for changes on all JS and CSS files.
*
* Live reload is working (servers running on localhost 35729 and 35728).
* You'll need a Live-reload plugin installed (https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei)
*
* Changes to grunt file will rerun the grunt script.
*/
watch: {
css: {
files: ['style.scss'],
tasks: ['sass:compile']
},
configFiles: {
files: ['Gruntfile.js'],
options: {
reload: true
}
}
},

/**
* Converts all ES6 Javascript into ES5 Javascript.
*
* .babelrc full configures Babel.
*/
babel: {
/**
* Transform ES6 JS files into ES5.
*/
es6: {
options: {
sourceMap: true,
presets: ['es2015'],
},
files: {
// "client.js": "public/js/prod.js"
"public/js/prod.js": "client.js",
},
},
},
});

grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-babel');

grunt.registerTask('development', ['sass:compile', 'watch']);
grunt.registerTask('production', ['sass:compile', 'babel:es6']);
};
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@
# afx
# afx

## Setup

Install the package dependencies: `npm install`.

Copy the pre-commit Git hook, to ensure the assets are compiled before you commit.
```
cp pre-commit .git/hooks/.
```

## Development

```
grunt development
```
254 changes: 254 additions & 0 deletions client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@

class TextScramble {
/** Modified version of Justin Windle's Text Scrambler: https://codepen.io/soulwire/pen/mErPAK */

constructor(el, scrambleSpeed, chars) {
this.el = el;
this.scrambleSpeed = scrambleSpeed || 25;
this.chars = chars || 'aphextwin';
this.update = this.update.bind(this)
}

setText(newText) {
window.countdowner.updateField = false;
const oldText = this.el.innerText;
const length = Math.max(oldText.length, newText.length);
this.queue = [];

for (let i = 0; i < length; i++) {
const from = oldText[i] || '';
const to = newText[i] || '';

const start = Math.floor(Math.random() * (this.scrambleSpeed));
const end = start + Math.floor(Math.random() * (this.scrambleSpeed));

this.queue.push({ from, to, start, end })
}
cancelAnimationFrame(this.frameRequest);
this.frame = 0;
this.update();
}

update() {
let output = '';
let complete = 0;
for (let i = 0, n = this.queue.length; i < n; i++) {
let { from, to, start, end, char } = this.queue[i];
if (this.frame >= end) {
complete++;
output += to
} else if (this.frame >= start) {
if (!char || Math.random() < 0.28) {
char = this.randomChar();
this.queue[i].char = char
}
output += `<span class="dud">${char}</span>`
} else {
output += from
}
}
this.el.innerHTML = output;
if (complete === this.queue.length) {
window.countdowner.updateField = true;
return;
} else {
this.frameRequest = requestAnimationFrame(this.update);
this.frame++
}
}

randomChar() {
return this.chars[Math.floor(Math.random() * this.chars.length)]
}
}

function padWithDots(str) {
let maxPadding = 40;
let numToAdd = maxPadding - str.length;

let dots = '';
for (let i=0; i < numToAdd; i++) {
dots = dots + ".";
}

return str + dots;
}

class Countdown {
constructor() {
let that = this;
let a = new Date().valueOf();
let b = 1499119200000;
let d = 1496520000000;

this.$el = $('#countdown');
this.updateField = true;
this.c = b - a;

this._setText();
setInterval(function() {
that.c = Math.floor((that.c - (100 * ((b - a) / (d - a)) ) )) ;
that._setText();
}, 100);
}

_setText() {
if (this.updateField) {
this.$el.text( padWithDots(this.c + "") );
}
}
}

function initScramblers() {
window.countdowner = new Countdown();
const countdownScrambler = new TextScramble(document.getElementById('countdown'), 15, 'aphex');

$('#nts-label').text(padWithDots("NTS"));

let $paddingElements = $('.aphexDotPadding');
let paddingScramblers = [];
$paddingElements.each( function(i) {
let $el = $($paddingElements[i]);
$el.length && $el.text( padWithDots(""));

paddingScramblers.push( new TextScramble($paddingElements[i], 25, i % 2 === 0 ? 'twin' : 'aphex'));
});

let scrambleText = function() {
for(let i=0; i < paddingScramblers.length; i++) {
paddingScramblers[i].setText(padWithDots(""));
}

countdownScrambler.setText( padWithDots(window.countdowner.c + "") );

let rangeInSeconds = 4.5;
let randomTimeout = Math.floor( (Math.random() * 1000) * rangeInSeconds);

setTimeout(scrambleText, randomTimeout)
};

scrambleText();
}

let NTS_AFX = {};
NTS_AFX.store = {
init: function() {
let config = {
apiKey: "AIzaSyCn2JexWTvW3fyvyvjWNcdwe-wDkgOw1c0",
authDomain: "nts-afx.firebaseapp.com",
databaseURL: "https://nts-afx.firebaseio.com",
projectId: "nts-afx",
storageBucket: "nts-afx.appspot.com",
messagingSenderId: "1740064170"
};
firebase.initializeApp(config);
},
post: function(message) {
let record = { message: message };
let newPostKey = firebase.database().ref().child('messages').push().key;
let updates = {};
updates['/messages/' + newPostKey] = record;
return firebase.database().ref().update(updates);
}
};

(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-6061419-3', 'auto');

class AudioPlayer {
constructor() {
this.el = document.getElementById('aphex-audio');

this.el.addEventListener('play', function(e) {
$('#player').addClass('playing');
});
this.el.addEventListener('pause', function(e) {
$('#player').removeClass('playing');
});

this.el.volume = 0.8;
}

play() {
this.el.play();
}

pause() {
this.el.pause();
}

isPlaying() {
return !this.el.paused;
}

toggleAudio() {
this.isPlaying()
? this.pause()
: this.play();
}
}

$(document).ready( function () {
ga('send', 'pageview', window.location.pathname);

initScramblers();
NTS_AFX.store.init();

window.audioPlayer = new AudioPlayer();

let $consoleEntryForm = $('#console-entry-form');

$consoleEntryForm.focus();
$consoleEntryForm.submit( function(e) {
e.preventDefault();

ga('send', 'event', 'Aphex', 'PasswordAttempt');

let authenticated = NTS_AFX.store.post(
e.currentTarget.children['console-entry'].value
).then(function(authenticated) {

if (authenticated) {
let $msg = $('#success-message');
$msg.addClass('display');

setTimeout(function() {
$msg.removeClass('display');
},2000);

authenticated.authenticate();
} else {
let $msg = $('#error-message');
$msg.addClass('display');

setTimeout(function() {
$msg.removeClass('display');
}, 1500);
}

e.currentTarget.children['console-entry'].value = "";
});
});

$('#nts-link').on('click', function() {
ga('send', 'event', 'Aphex', 'GoTo-NTS');
});

$('#warp-link').on('click', function() {
ga('send', 'event', 'Aphex', 'GoTo-Warp');
});

$('#player').on('click', function() {
window.audioPlayer.toggleAudio();
});
});
Loading