Skip to content

Instantly share code, notes, and snippets.

View thomaswilburn's full-sized avatar
🦝

Thomas Wilburn thomaswilburn

🦝
View GitHub Profile
@thomaswilburn
thomaswilburn / geocoding.md
Last active November 14, 2023 08:57
So You Want to Geocode an Address in Sheets

If you have fewer than a thousand addresses and you need them geocoded quickly and accurately, Google Sheets is generally the best way to do it. Here's how to set up the Apps Script necessary. Here is a demo sheet with everything set up, including the Apps Script code.

Create or open your sheet, and then in the Extensions menu, choose "Apps Script" to open the editor. Erase the placeholder contents in Code.gs and paste this in:

const SHEET_NAME = "data";
const ADDRESS_COLUMN = 2;
const LATITUDE_COLUMN = 3;

function geocode() {
@thomaswilburn
thomaswilburn / Repair.gs
Created September 6, 2014 20:23
Geocoding using Apps Script APIs
var sheet = SpreadsheetApp.openById(sheetID).getSheetByName("Responses");
var rowConfig = "timestamp name location favorite note lifespan season contact lat lng city zone approve feature".split(" ");
function getCol(row, param) {
return row[rowConfig.indexOf(param)];
}
function setCol(row, param, value) {
row[rowConfig.indexOf(param)] = value;
@thomaswilburn
thomaswilburn / decode.js
Last active July 15, 2023 05:06
Decoding function for Google's polyline encoded strings
/*
This is more complicated than it would normally be, because A) it delivers
output in pairs, and B) those pairs are all offsets from the previous pair.
If you're just delivering a stream of values, this is about 1/2 as long.
*/
function decode(str) {
// last known coordinate for adding offsets
var from = [0, 0];
var value = 0;
var shift = 0;

Development By Proxy

There's an argument that if you use private class fields in JavaScript, your code is incompatible with Vue (and other frameworks that use proxies to provide reactive data binding). That's interesting! Why is that? And is it actually impossible to use private fields with @vue/reactivity? To find out, let's take a look at how both private fields and proxies work in JavaScript, and see some possible solutions.

How Proxies break Vue

A proxy in JavaScript is an object that can stand in for another and "trap" various operations, like calling methods or getting/setting properties. They're useful for mocking or logging, because you can effectively wrap an object in a proxy and see (or interfere with) all the actions that code takes on that object, without having to actually touch either side of the original code.

Here's a quick example:

@thomaswilburn
thomaswilburn / re-iterate.md
Last active April 30, 2023 13:26
Putting JavaScript's iterable protocol into context

Re: Iterate

I'm so old I remember when arrays in JavaScript didn't have forEach() or map(), and a lot of libraries would implement their own functional looping constructs, which were better than regular loops because you got a new function scope (remember, we didn't have let or const either). We all had to adjust when native forEach() landed because we were used to jQuery's each(), which had the arguments in the wrong order.

I was reminded of this while doing some scraping last week using Cheerio to load and traverse an HTML page in Node. Cheerio implements a jQuery-like API, which is genuinely pleasant to use, but carries some of that legacy behavior (like each(index, item) argument ordering) with it in ways that are jarring if you haven't used actual jQuery in a while. Fortunately, Cheerio also implements the iterator protocol on its collections, so if you just want the items for a given selector, you can use for ... of loops and not have to think abo

@thomaswilburn
thomaswilburn / Code.js
Last active September 28, 2022 13:00
=importJSON support for Sheets, producing keypath/value pairs
function IMPORTJSON(url) {
var response = UrlFetchApp.fetch(url);
var text = response.getContentText();
var json = JSON.parse(text);
var output = [];
var step = function(at, value) {
if (value instanceof Array) {
for (var i = 0; i < value.length; i++) {
@thomaswilburn
thomaswilburn / download_sheet.deno.js
Created August 11, 2022 14:23
Download a Google sheet via Deno
import * as google from "https://esm.sh/@googleapis/sheets";
import { stringify } from "https://esm.sh/csv-stringify/sync";
var clientID = Deno.env.get("GOOGLE_OAUTH_CLIENT_ID");
var secret = Deno.env.get("GOOGLE_OAUTH_CONSUMER_SECRET");
var spreadsheetId = "1R78UCHNrc2VrTuObhduVZNpgSZJDV5-kuw8S4gzJV9k";
var HOME = Deno.env.get("HOME");
@thomaswilburn
thomaswilburn / media-favicon.js
Created May 25, 2022 16:43
Add a favicon with media playback progress in Firefox
var canvas = document.createElement("canvas");
canvas.width = canvas.height = 32;
var context = canvas.getContext("2d");
var link = document.createElement("link");
link.setAttribute("rel", "icon");
var media = document.querySelector("audio, video");
media.addEventListener("timeupdate", function() {
// get the current ratio
@thomaswilburn
thomaswilburn / tcaer.md
Created May 9, 2022 15:23
React but make it imperative

What if React was imperative instead of being functional?

When you write JSX, it compiles down to nested calls to createElement() (or the equivalent, I don't know if that's still the function React uses). Because this ends up being a single recursive function call, you can only use value expressions inside the code--that's why you have to map() when you loop, and you have to use ternaries instead of actual conditional statements.

Over time, the React team's thinking about architecture has clearly shifted a lot, to the point now where hook functions create implicit, hidden state that's preserved in the order of the function calls. What if JSX worked this way? What if when you wrote a template, instead of a single function call with nested expressions, it used imperative, IMGUI-like function calls instead? In that case, the raw code might look something like this:

template(html => {
  var { footer, a, button, text, div, ul, li } = html;
  div`.outer`;
@thomaswilburn
thomaswilburn / keymap.c
Last active April 3, 2022 13:52
QMK retro toggle lighting for CTRL
#include "print.h"
#include QMK_KEYBOARD_H
enum ctrl_keycodes {
L_BRI = SAFE_RANGE, //LED Brightness Increase //Working
L_BRD, //LED Brightness Decrease //Working
L_EDG_I, //LED Edge Brightness Increase
L_EDG_D, //LED Edge Brightness Decrease
L_EDG_M, //LED Edge lighting mode
L_PTN, //LED Pattern Select Next //Working