Borderlist – I made a thing

So listen, I made a thing. Yes, it is another to do app thingie but this one is built a bit differently. I work from so many lists on any given day that it is difficult to see everything at a glance.

I want to

  • See multiple lists at a time around the same topic.
  • Make a list, add some items, get stuff done, tick’em off.
  • Delete lists and clear my boards.
  • See it all on my phone without having to download yet another app.

No bells and whistles. No fluff.
I want a disposable Post-It Note system without all the sticky pads.

With these goals in mind I built Borderlist. It’s free, simple, and I use it every day.

Visit Borderlist

Because this is a tech blog, here are some nerdy details. The front end is built with Bulma (CSS) and, once in an account, it is all Vue using a Laravel based API to handle the data.

If you decide to give it a try, let me know what you think.

Fixing gulp-include error of “no files found matching…” when the file exists

In using gulp to include files inline I ran into a bit of an error. gulp-include kept throwing the following error:

WARN: gulp-include – no files found matching [file_path_here]

These types of errors drive me crazy. The file was exactly where it was supposed to be. I checked it several times. What gives?! Turns out, gulp-include feels that finishing the include line with a semicolon is a deadly sin.

// remove the ending semicolon from include #include "lower_third_module"
module.jsx

Changing all includes to remove the semicolon did the trick. Here’s the gulp file for reference.

const gulp = require('gulp'); const replace = require('gulp-replace'); const include = require('gulp-include'); gulp.task("myTask", function() { gulp.src("src/lower_third_script.jsx") .pipe(replace("#include", "//=include")) .pipe(include()) .on('error', console.log) .pipe(gulp.dest("dist")); });
module.jsx

If you found this article, hopefully it will help you. Happy typing.

Getting Bootstrap, jQuery, Laravel-Mix and Electron to Play Together

While testing out Electron I wanted to begin building something with Bootstrap (my favorite “get-it-done” CSS framework). Since Electron requires build steps I’m going to use Laravel-Mix to handle getting Bootstrap 4, jQuery and Electron to work together.

The biggest challenge was running down a Bootstrap error when trying to compile jquery.min.js, bootstrap.min.js and tether.min.js into a single vendors.js file:

Uncaught Error: Bootstrap’s JavaScript requires jQuery. jQuery must be included before Bootstrap’s JavaScript.

Turns out, jQuery, when compiled is a module and not attached to the browser “window.” This means that jQuery or $ calls don’t resolve because window.jQuery or window.$ do not exist.

I got it all sorted out by pulling jQuery out of vendors.js and adding a require in the head on page. The resulting head of my Electron’s index.html looks like so (I have my html in a single folder in my electron project):

You may see an error here but don’t worry. In Electron (at least in their starter samples) the final script tag is below the closing body tag.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Electron Thingie</title> <link rel="stylesheet" href="../dist/app.css"> <script> window.$ = window.jQuery = require('../node_modules/jquery/dist/jquery.min.js') </script> <script src="../dist/vendors.js"></script> <script src="../dist/app.js"></script> </head> <body> <!-- BUILD A THING --> </body> <script> // You can also require other files to run in this process require('../renderer.js') </script> </html>
index.html

You may see an error here but don’t worry. In Electron (at least in their starter samples) the final script tag is below the closing body tag.

If you’re interested, my package.json looks like so:

Dropped in Bootstrap, jQuery, Laravel-Mix and Electron. Also add a few scripts to speed up development.

{ "name": "electron-starter", "version": "1.0.0", "description": "", "main": "main.js", "scripts": { "start": "electron .", "webpack": "cross-env NODE_ENV=development webpack --progress --hide-modules", "dev": "cross-env NODE_ENV=development webpack --watch --progress --hide-modules", "hmr": "cross-env NODE_ENV=development webpack-dev-server --inline --hot", "production": "cross-env NODE_ENV=production webpack --progress --hide-modules", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "bootstrap": "^4.0.0-alpha.6", "jquery": "^3.1.1", "laravel-mix": "^0.3.0", "electron": "^1.4.1" } }
package.json

And my build steps are insanely simple thanks to Laravel-Mix:

let mix = require('laravel-mix').mix; mix.combine([ 'node_modules/tether/dist/js/tether.js', 'node_modules/bootstrap/dist/js/bootstrap.js' ], 'dist/vendors.js'); mix.js('src/app.js', 'dist/'); mix.sass('src/app.scss', 'dist/');
webpack.mix.js

You’ll want to follow Laravel-Mix’s installation docs to get mix in place once you install the dependency.

Creating and Destroying Javascript Timeouts on the Fly

In Javascript, sometimes you just have to wait a few millisecond before you perform a task. A few examples

  • Assets need just a small window of time to render on screen
  • A button opens an overlay window and you want to close it after a set amount of time.
  • Delay an element animating in while you perform some other on page tasks.

All good things, all good things. Sometimes you may need to kill the delayed event after it was create but before it was performed. Let’s say you want a button to display something on screen and fade out after 5 seconds IF the user doesn’t close the element first.

var closeAThing = setTimeout(function() { console.log('remove thing automatically from screen'); }, 5000); $('.btn-close').click(function(evt) { evt.preventDefault(); console.log('remove the thing manually'); clearTimeout(closeAThing); });

Not to bad. But these variables are stored in a global scope and, every time you create one, you’re increasing the chance of a name collision unless you are careful with your variable conventions. So, to get around all this, here’s what I did. Maybe you’ll find it useful.

/* * ############################################### * Initialize Variables * ############################################### */ var pageTimeouts = {}; /* * ############################################### * Functions * ############################################### */ // set timeouts by name function createTimeout(name, func, time) { destroyTimeout(name); pageTimeouts[name] = setTimeout(func, time); } // destroy a timeout by name function destroyTimeout(name) { if (pageTimeouts.hasOwnProperty(name)) { clearTimeout(pageTimeouts[name]); } }

Why is this better? For one, it stores all timeouts in a single global object. That is kinda handy. It also cleans up creation, destruction, and checks if there is timeout of the same name and clears it before creating another. With this method, now you can create and destroy timeouts on the fly like so…

$('a.btn').on('click', function(evt) { evt.preventDefault(); $('.alert').addClass('animated bounceIn'); createTimeout('alert', function() { $('.alert').attr('class', ''); }, 5000); }); $('.alert a.close').on('click', function(evt) { evt.preventDefault(); $('.alert').attr('class', ''); destroyTimeout('alert'); });

I think it is pretty nifty. Hope it helps.