Sunday, June 27, 2021

pell, granted: minimalist javascript install of a minimalist wysiwyg html editor

For obvious reasons 2020 was a pretty quiet year for Porchfest, and this year I am playing catch up on the website stuff, blowing off all the dust and continuing the effort to get every porchfest site running on the same tech base.

An underbaked feature has been the ability for admins to edit various snippets on the site. Few admins are fluent in HTML, so my crude "edit the raw source code" was less than ideal. 

I browsed around for various options. The one I landed on was Pell, a super-minimalist but still pretty well-featured editor. That page has the demo, the github page has some installation instructions, but it's kind of a mix of "run it from <script src> tags and code that looks like it's assuming there's going to be a build process.

Here's what I ended up with, my final Proof of Concept before integrating the tech into the Porchfest site:

<head>  
  <link rel="stylesheet" type="text/css"
     href="https://unpkg.com/pell/dist/pell.min.css">
  <style>
    .pell-content {
      background-color: #eee;
    }
  </style>
</head>
<body>
  <div id="editor" class="pell"></div>

<form action="/form/" method="POST">
    <input name="content" type="hidden" id="content" />
    <button>Save Changes</button>
</form>
  <script src="https://unpkg.com/pell"></script>
<script> window.pell.init({ element: document.getElementById('editor'), onChange: html => document.getElementById('content').value = html }); const start = '<b><u><i>Initial content!</i></u></b>'; document.getElementById('editor').content.innerHTML = start; document.getElementById('content').value = start; </script> </body>

So, I just tuck the script stuff at the end, after the page is loaded, I seed the editor and a hidden input field with the content, and then the onChange keeps the hidden input field up to date, and then I can submit that to a form.

I have to find out how tolerant the editor is of crappy HTML that might have been in the system before, but this is really promising!

https://github.com/jaredreich/pell also has a list of similar editors, comparing size and what not)

Friday, June 18, 2021

old man yells at (the) cloud

Or Web-Development is running into the wrong direction.

It does make one ponder the Rise and Fall of JQuery.

I think its main problem is that it never had a great solution for how to tie in buttons on their actions, and frankly pre fat-arrow and pre-good-scoping Javascript was a mess... anytime you had to think about "this" was a trainwreck.  And there wasn't a great way to import a module. 

And now, most of the standardization it provided is handled with more mature browsers and a lot of the syntactic sugar is moved into vanilla JS. But You May Not Need JQuery as a translation glossary demonstrates that many of the ideas it brought to the table were worth keeping.

Still, I think it's more a need to make front end programming feel more like back end programming is what stinks right now. "front end programmers won't feel respected and be happy til they have a build process that's as long as the back end" was my prophecy, and I think that's about right. 

making formik-powered components that still work without formik

On my team we are making a component library, and we decided to make our components Formik aware, so that when used in a Formik context they would populate themselves, handle the onChanges, detect and show errors (using Yup validation) etc. But we also wanted them to continue to work OUT of the Formik context. But when we did so, we'd see this error in the. console:

Warning: Formik context is undefined, please verify you are calling useFormikContext() as child of a <Formik> component.

We were grabbing the Context using

import { FormikContext, useFormikContext } from 'formik';
//...
const formikContext = useFormikContext();

Weirdly we get better results (i.e. no warnings) by using React's useContext instead:

import React, { useContext } from 'react';
import { FormikContext } from 'formik';
//...
const formikContext = useContext(FormikContext);

Not quite sure why that works, but it does.

(Another small Formik point - it might be more or less obvious from the examples, but you probably want to make sure you only display contents of formik.errors['thisValue'] if formik.touched['thisValue'] is true. However, the usual submit handling will set all touched values to be true. Which seems weird at first, but makes sense in practice - that's as touched as those components are going to get!)

Thursday, June 17, 2021

icon art circa 1994

For a brief time in the early 90s I was the "webmaster" for Tufts University's Comp Sci department. I hand drew some icons for the homepage - strong Keith Haring energy.



Tuesday, June 15, 2021

cute little apple ui feature: playlist thumbnails

I'm very set in my musical ways: I like purchasing single mp3s (or the equivalent), and then resorting to youtube rips if I have no other option. I've rated all my music ever since my iPod only had room for "3 stars and up", and then have good, better, best (3+ stars, 4+, and 5, respectively) smart playlists, and then try to listen to the "good" playlist (in reverse chronological order) daily, so I form a connection with the music. 

Anyway, Apple has a curious algorithm for assembling a thumbnail for a playlist, and mine has been consistent for a long while:



I think it's picking "A,B,C,D" so in my case, Ani "Buildings + Bridges" DiFranco, BPA ("Toe Jam" with David Byrne - fun sort of NSFW video for that), CAKE ("The Distance" was my senior solo), and Dar "Cool As I Am" Williams.


Monday, June 14, 2021

what makes Apple's M1 so good?

By all reports, Apple has done something miraculous with its M1 chip - like every chip maker is doing as good of a job as it can, and then Apple is like Homer as the new manager at the Bond-ish Villain's Nuclear Plant:


Here's a good article going into how the M1 stands out.

Its interesting that Apple's secret sauce is System-on-a-Chip, and intense specialization (I mean even the earliest iPhone blew other devices out of the water in terms of responsiveness, in part because of custom scrolling hardware. At the time I thought about the old Amiga and Atari ST, and how much more interesting game machines they were than the PC, it took the PC years to catch up with sound and graphic cards - its own custom hardware, but less well-integrated) But that specialization seems to be at cross-purposes to how Apple is using the same chip family for all devices: from Watches through Phones and iPads and Macs.

Cool times for Apple fans!

Friday, June 11, 2021

quality assured humor

A joke from Bad Jokes by Jeff:

A software tester walks into a bar

Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a bear. Orders -1 beers. Orders hdtseatfibkd.

First real customer walks into a bar and asks where the bathroom is. The bar bursts into flames killing everyone inside.

Wednesday, June 9, 2021

"contenteditable" div as replacement for textarea that stretches to fit content

 A while back I made this simple invoice maker and I decided I wanted to make the line items multiline. But it seems like it's weirdly hard to get a textarea to stretch to content! One suggestion from that page is to make a div with the "contenteditable" property... then you get the usual div niceness of stretching to fit content. 

I had to come up with a javascript hack to copy the div contents into hidden form variables onsubmit:

    function loadDescAsHidden(){

        window.desc1.value = window.desc1div.innerHTML;

        window.desc2.value = window.desc2div.innerHTML;

        window.desc3.value = window.desc3div.innerHTML;

    }

So not the prettiest, but good enough for my purposes.

Sunday, June 6, 2021

ui hall of shame: HBO Max on Samsung TVs

Daring Fireball linked to an article HBO Max tvOS Update Breaks Several Key Features, Degrading Experience Significantly. One thing I've noticed is that the HBO Max app on my Samsung TV has been weirdly, uniquely bad... mostly because on every other app, the play/pause button pauses. On HBO Max it brings up a tutorial page for a random command Samsung's Bixby voice command features:

For unfathomable reasons, the inner button on the circle control, which means "OK" or "Select" everywhere else, is what is used for pausing. The overall effect is as if HBO let a Junior Dev release a half baked experiment with Samsung's API out without any user testing. 

(FWIW, I think the UI on the Samsung TV is pretty decent... light years ahead of the older Samsung my folks have. I'm told that Smart TVs are so cheap in part because they are subsidized by selling viewing information to advertisers. I'm actually ok with that bargain, to be honest - I guess I run a little insensitive on privacy issues as long as it's treating me as J Random Viewer and not someone specific.)

Friday, June 4, 2021

obscure html tag attribute of the day: spellcheck="false"

 Huh! My screenshots for my Timesheet Tim "meme"-thingy were marred by red underlines for misspelled words (attempts to capture a Dickens-esque or faux-Cockney accent in writing, attempts that make Dick Van Dyke look pretty good) but I found out a 

spellcheck="false"

on the textarea works pretty well. I think maybe it can on a form tag as well, and be inherited?

Thursday, June 3, 2021

hiding out from the const cops

 So, some of my coworkers are much more fired up about insisting on the use of const for javascript variables than I am. I think it's a bit of a shame, especially because nothing stops you from doing:

const foo = { bar: 123};
foo.bar = 456;

There are different ways of freezing an object like that, but I think people who care about const think of it like a "Poor Man's Immutable". 

So I was surprised when code like this showed up in a Pull Request:

const someFunction = ( { bar } ) => {
    // some other work
    bar = 456;
}

I guess I assumed properties were const... but no. And in fact, there's not a clean syntax for it, that keeps up with the syntactic sugar.

On the WesBos slack domain, A-J Roos says:

You’d have to destructure from the arguments object if you don’t want the variables to be reassigned.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments

TypeScript has a readonly type that you can use to define function arguments that cannot be reassigned during development.

https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype

So, huh.