diff --git a/.gitignore b/.gitignore index 37d7e73..253799d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules .env +public/dist diff --git a/bin/broadcast.js b/bin/broadcast.js index 2b3bb59..e7bc32c 100644 --- a/bin/broadcast.js +++ b/bin/broadcast.js @@ -4,7 +4,6 @@ var WebSocketServer = require('ws').Server; var wss = new WebSocketServer({ port: 8080 }); process.stdin.on('data', function (data) { - console.log('data:', data.toString().trim()); wss.clients.forEach(function each(client) { client.send(data.toString().trim()); }); diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..aebe8a0 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,104 @@ +'use strict'; + +var gulp = require('gulp'); +var util = require('gulp-util'); +var jshint = require('gulp-jshint'); +var less = require('gulp-less'); +var sourcemaps = require('gulp-sourcemaps'); +var browserify = require('browserify'); +var source = require('vinyl-source-stream'); +var buffer = require('vinyl-buffer'); +var babelify = require('babelify'); +var uglify = require('gulp-uglify'); + +var publicJsDir = 'source/js'; +var publicJsRoot = './' + publicJsDir + '/main.js'; +var jsDest = './public/dist'; +var jsMin = 'main.min.js'; + +var jsGlob = ['package.json', 'gulpfile.js', 'app/**/*.js', 'source/**/*.js']; + +var lessSrc = 'source/less/main.less'; +var lessSrcGlob = ['source/less/**/*.less']; +var lessDest = 'public/dist'; + +gulp.task('lint', function() { + gulp.src(jsGlob) + .pipe(jshint({ + esnext: true, + curly: true, + eqeqeq: true, + eqnull: true, + globalstrict: true, + camelcase: true, + indent: 2, + immed: true, + latedef: 'nofunc', + newcap: true, + quotmark: true, + undef: true, + unused: true, + trailing: true, + node: true, + browser: true, + globals: { + Range: true, + Promise: true, + $: true + } + })) + .on('error', handleError) + .pipe(jshint.reporter('jshint-stylish')); +}); + +gulp.task('browserify', function() { + var bundler = browserify({ + entries: [publicJsRoot], + debug: true + }); + + var bundle = function() { + return bundler + .transform(babelify) + .bundle() + .on('error', util.log.bind(util, 'Browserify Error')) + .pipe(source(jsMin)) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(uglify()) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(jsDest)); + }; + + return bundle(); +}); + + +gulp.task('less', function () { + gulp.src(lessSrc) + .pipe(less({ + paths: [], + compress: true + })) + .on('error', handleError) + .pipe(gulp.dest(lessDest)); +}); + +gulp.task('watch', function () { + gulp.watch(jsGlob, ['lint', 'build_js']); + gulp.watch(lessSrcGlob, ['build_css']); +}); + +gulp.task('build', ['build_js', 'build_css']); +gulp.task('build_js', ['lint', 'browserify']); +gulp.task('build_css', ['less']); + +gulp.task('default', ['build', 'watch']); + + +/* Helpers +============================================================================= */ + +function handleError (error) { + util.log(error.message); +} diff --git a/package.json b/package.json index 5ac7953..a6f45ba 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,19 @@ "ws": "^0.7.1" }, "devDependencies": { - "http-server": "^0.8.0" + "http-server": "^0.8.0", + "babelify": "^5.0.4", + "browserify": "^9.0.3", + "browserify-shim": "^3.8.3", + "gulp": "^3.8.11", + "gulp-jshint": "^1.9.2", + "gulp-less": "^3.0.1", + "gulp-sourcemaps": "^1.5.0", + "gulp-uglify": "^1.1.0", + "gulp-util": "^3.0.4", + "jshint-stylish": "^1.0.1", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.1.0" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", diff --git a/public/index.html b/public/index.html index 4acf72a..e5419b2 100644 --- a/public/index.html +++ b/public/index.html @@ -3,14 +3,11 @@ Listen + - +
+ + diff --git a/source/js/main.js b/source/js/main.js new file mode 100644 index 0000000..332dbb1 --- /dev/null +++ b/source/js/main.js @@ -0,0 +1,12 @@ +'use strict'; + +var socket = new WebSocket('ws://localhost:8080'); +var thematrix = require('./thematrix'); + +socket.onmessage = (e) => { + console.log(e.data); + thematrix.draw(e.data.split('|')); +}; + +socket.onopen = () => console.log('Connected'); +socket.onclose = () => console.log('Disconnected'); diff --git a/source/js/thematrix.js b/source/js/thematrix.js new file mode 100644 index 0000000..0a5c9e0 --- /dev/null +++ b/source/js/thematrix.js @@ -0,0 +1,35 @@ +'use strict'; + +var thematrix = $('#thematrix'); + +var width = thematrix.width(); +var height = thematrix.height(); + +var createChar = (text) => { + return $('
').addClass('char').text(text); +}; + +var killWhenDone = (elem, length) => { + //## Really ugly + setTimeout(() => { + elem.remove(); + }, length * 200 + 2000); +}; + +var createCol = (text) => { + var col = $('
').addClass('col'); + + text.split('').forEach(c => col.append(createChar(c))); + + col.css({ + left: Math.floor(Math.random() * width), + top: Math.floor(Math.random() * height) + }); + + killWhenDone(col, text.length); + return col; +}; + +exports.draw = ([type, id]) => { + thematrix.append(createCol(id)); +}; diff --git a/source/less/main.less b/source/less/main.less new file mode 100644 index 0000000..9225b93 --- /dev/null +++ b/source/less/main.less @@ -0,0 +1,70 @@ +body { + background-color: #000; + overflow: hidden; + margin: 0; + padding: 0; +} + +.thematrix { + background-color: #000; + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + color: #090; +} + +.col { + display: block; + width:1px; + margin-right: 20px; + float: left; + position: absolute; + font-family: monospace; + font-weight: bold; + text-align: center; + white-space: pre; + word-wrap: break-word; +} + +.char { + opacity: 0; +} + +@interval: 40ms; +@visible-for: 2000ms; + +.animate-char (@n) when (@n > -1) { + .animate-char(@n - 1); + + .char:nth-child(@{n}) { + -webkit-animation: + fade (@visible-for) linear (@n * @interval) 1; + } +} + +.animate-char(100); + +@-webkit-keyframes fade { + 0% { + opacity: 0; + color: #dfd; + } + 1% { + opacity: 1; + color: #dfd; + } + 5% { + opacity: 1; + color: #090; + } + 97% { + opacity: 1; + color: #090; + } + 100% { + opacity: 0; + color: #090; + } +}