Reflections on a particularly rough week for race relations in America in 2016

Note: I initially posted this on Facebook. But things on Facebook have a tendency to get lost in the noise. Better to also preserve it here in the musty silence of my blog.

Seeing some pretty extreme responses on social media from some white people in the wake of the past few days’ events. If I could say anything to white people who are scared and/or angry and/or, God forbid, arming themselves for a race war, it would be this:

Social justice is not a zero sum game. You don’t have to do worse for others to do better. To quote the late, great Paul Wellstone, “We all do better when we all do better.”

You may have a vision of what “America” is, or what an “American” is, and that vision may be a particular color. But Americans who aren’t white are still Americans, just as much as you are.

Black Americans who are reacting to their friends and relatives being gunned down by police at routine — far too routine for many of them — traffic stops have a right to be scared, and angry. But Black Lives Matter is not about revenge. It’s not about starting a war. It’s about JUSTICE. About bringing more PEACE to our streets, our cities, our country. It’s about the “American” in “African American.”

At least, that’s how I see it. And living in the city, I’m probably in much closer proximity to BLM than most white Americans who are themselves scared or angry right now. So please, don’t be. Stop. Listen. Think. Feel. Understand.

Our fellow Americans who weren’t born with the inherited privileges conferred by white skin are living under the burden our ancestors placed on them — a burden that we perpetuate every day that we don’t actively acknowledge and work to counteract it. Hear their voices. Amplify them. Don’t silence them.

And when something happens like the shootings in Dallas, wait for the facts. BLM is a peaceful movement. Dallas PD has a good relationship with BLM. Officers were there to PROTECT the BLM marchers. The shooters do not represent Black Lives Matter or its goals.

I could go on, but I’ve already spoken too long. But don’t stop listening. Seek out those voices that are demanding peace and justice and hear what they are saying. And I will continue trying to do the same.

Thinking out loud on Twitter about the new Minneapolis paid sick time rules

No further commentary, but I wanted to gather up my thread of tweets on this topic from today.

First, the news behind it: Minneapolis paves way to give thousands of workers paid sick time

Here’s what I had to say, as I thought through things on Twitter. (I know I should have used Storify or embedded tweets or something but a screenshot of the whole thread was easier.)

Screen Shot 2016-05-27 at 9.42.34 AM

Web developers: learn how to Google. If no one else has the same problem, the problem is you.

OK, maybe not you per se. This is not a judgment of your merits as a developer, or as a human being. But it does mean the problem is almost certainly something specific to the code you’ve written.

The Hierarchy of Coding Errors

If your code isn’t working, the source of the problem is one of the following, in order from most likely to least likely:

  1. New procedural code you’ve just written
  2. New object-oriented code you’ve just written*
  3. Custom functions or objects you built, but have used before
  4. Third-party/open source add-ons to the software platform you’re using (e.g. WordPress plugins)
  5. Standard functions or objects in the software platform (e.g. WordPress core)
  6. Public code libraries that are included in your chosen software platform (e.g. jQuery)
  7. Browser bugs
  8. OS bugs
  9. Internet protocol bugs
  10. Quantum fluctuations in the fabric of spacetime
  11. Gremlins

You may have guessed correctly at this point that this blog post is not just idle Friday afternoon musings. I’ve spent the majority of the day today troubleshooting a very strange issue with a website I’m currently building. I fixed the problem, but not after being forced to — once again — confront this humbling reality. If something’s not working, it’s probably your own fault. Especially if you’re the only person with the problem.

Googling the issue got me (almost) nowhere… which was the most obvious clue that it was my own fault

Aside from the natural human inclination to deflect blame, the tools we have for troubleshooting these types of problems are not necessarily well suited to forcing us to be honest with ourselves. It’s too easy to blame external forces.

Here’s my scenario. I found out last week while presenting work-in-progress to a client at their office that there was a JavaScript-related problem with the website. It only affected Internet Explorer (and Edge), which I had not yet tested the site in, and, weirdest of all, it didn’t always happen. I’d say maybe 10-20% of the time, the page loaded normally. But the rest of the time, it got an error.

Since this was only affecting one browser, my natural inclination was to start all the way at number 7 on the list, blaming Internet Explorer. But I’ve learned that as much as I want to blame it, issues with IE usually just shine a light on something in my own code that other browsers are more forgiving about. So it was time to walk backwards down the list. (Again… not really, but this is how it played out.)

The error that the browser reported was a “security problem” with jQuery Migrate. First I had to figure out what the hell jQuery Migrate was and why it was being loaded. (Turns out, it’s a place the jQuery team dumped deprecated code it pulled from version 1.9. It’s loaded by default by WordPress.)

With that in mind, this should be affecting every site I’ve built recently, since they’re all in WordPress. But it was only affecting this one site. So I had to try to narrow down where the problem exists. With WordPress, there are two main “variables” in the implementation: themes and plugins. When in doubt, try switching your theme and disabling the plugins you’re using. I started by disabling all of the plugins, one by one. No change. I found the error didn’t occur if I disabled Advanced Custom Fields, but that’s because half of the page didn’t load without it! (That’s another error on my part but let’s ignore that for now, shall we?)

OK, so it’s not a plugin. Next I swapped in the standard Twenty Sixteen theme in place of my custom theme. Not surprisingly, the error didn’t occur, but that didn’t help much because none of my Advanced Custom Fields content was in the pages. I still couldn’t rule out ACF as the culprit. But I tend to reuse field groups from site to site, so once again, if this were attributable to an ACF issue — even something specific to my field groups — it would’ve cropped up on another site.

So now I had little left to do but selectively comment out elements of the theme so I could narrow down where the problem was. (I make this all sound like a logical progression; in fact my debugging process is a lot more chaotic than this description — I actually did this commenting-out process haphazardly and repetitively throughout the afternoon.)

Eventually I pinpointed the troublesome block of code. Yes, it was #1 from the list. But as is usually the case with hard-to-diagnose problems, the complete picture here is that #1 included a combination of #3 and #5, which triggered an error message generated by #6, but only in the context of #7.

Yes. That’s what happened.

In the footer of the page, I had a link to the client’s email address. As is my standard (but by now probably outmoded) practice, I have a custom-built function I wrote years ago to obfuscate the email address by randomly converting most (but not all) of the characters in the string into HTML ampersand entities. My problem was not that function itself, which is tried and true. It’s that in this particular instance I called it on a string that included the mailto: pseudo-protocol, not just the email address itself.

I think the colon in mailto: is particularly significant to the problem, as evidenced by the fact that around 10-20% of the time the problem didn’t occur, and the page loaded normally. Since my obfuscation function randomly leaves characters in the string alone, that’s about how often the colon would have been kept untouched.

But even then, what difference should it make? Browsers decode those entity strings and can handle them in the href attribute of links just fine. However in this particular case I didn’t just use my obfuscation function. Without giving it much thought, in this particular site I had decided to wrap the obfuscated string in the standard WordPress esc_url() function. Trying to properly sanitize things, like a good developer. Right? Except — and I took a quick look at the source code to confirm it — there’s special handling in esc_url() for strings that don’t contain a colon. So the roughly 86% of the time that my string didn’t contain a colon, esc_url() was prepending http:// onto the string.

This situation was causing a particular piece of code in jQuery Migrate to barf… but only in Internet Explorer and Edge, for reasons I still don’t understand, but it has to do with how the different browsers handle security warnings in JavaScript. I found along the way (but before I had pinpointed the real problem) that if I commented out a particular segment of code in jQuery Migrate pertaining to the handling of selectors containing hashtags (see, the HTML ampersand entities again) I could get the page to load normally.

So, like I said, my newly written procedural code (#1), which itself included calls to both an existing custom function I wrote (#3) and a function baked into the WordPress core (#5), caused jQuery Migrate to issue an error (#6) but it was one that only a particular browser (Internet Explorer/Edge) cared to acknowledge (#7).

No wonder it took all afternoon to figure it out.

* The only reason I break out OO from procedural code is that OO has more structured patterns that are less likely to result in sloppy mistakes. Slightly.

WordPress dev tip: How to move the Featured Image box up… to just below the Publish box

Whenever I’m doing development on a WordPress site that makes heavy use of taxonomies (it happens with meta data-rich portfolios for architects, for instance, which seems to be a niche for me), I get really annoyed with how much WordPress devalues the Featured Image meta box. I don’t want it shoved way down below all of the taxonomies, mainly because users will probably forget or never even know that it’s there!

What I really want is to have the Featured Image box near — but not at — the top of the sidebar. Specifically, I want it to come just below the Publish meta box.

I’ve found some resources online that almost got me there, but not quite. However a minor tweak to this example solves the problem for me.

I’m taking some shortcuts here, some of which you may not like. First, most tutorials on manipulating meta boxes encourage you to remove them and then add duplicates with a slightly different ID. I think what’s happening here though (not having inspected the source code!) is that your modifications to the add_meta_boxes action run before the standard WordPress meta boxes get loaded (possibly/probably because, as you’ll see, we’re setting the priority to high), so if you’ve created one with the same ID as a default box, yours takes precedence.

The other shortcut I’m taking, which I suspect will be more controversial (but it’s just the way I like to do this) is that I am creating an anonymous function directly within the add_action() call. That’s just a personal preference, but I like to do it because 1) it keeps the code more compact and 2) it avoids creating a bunch of named functions that have no business ever being called anywhere else anyway.

So what’s happening here? First, I’m creating the Publish meta box. Then I’m creating the Featured Image meta box. By giving them both high priority, WordPress makes them the first two meta boxes in the sidebar. The reason I have to create the Publish meta box is that, if I didn’t, Featured Image would come first, above it. I don’t want that.

I’ve set the $screen parameter to null so this will happen on all editing screens, but if you only wanted to move Featured Image up on posts and not on pages, for example, you could set it to 'post'.

Here’s the full code:

add_action('add_meta_boxes', function() {
  add_meta_box('submitdiv', __('Publish'), 'post_submit_meta_box', null, 'side', 'high');
  add_meta_box('postimagediv', __('Featured Image'), 'post_thumbnail_meta_box', null, 'side', 'high');
});

For more background, check out the official documentation on the add_meta_box() function.

What’s in my bag?

Sounds like a dare to me. How can I resist?

bag1a

First, the bag itself. I love Tom Bihn bags. In addition to this backpack and its clip-in accessory pouches, I own two messenger bags and an assortment of other pouches. They are super high-quality and supremely functional. As you’ll see when I show you how much stuff I can cram into this bag and still have plenty of room to spare!

Let’s look at the contents of the red pouch. That’s where I keep adapters and thumb drives.

bag2

Oh, and an iPod nano, for some reason.

I need napkins (and/or paper towels) a lot. I can’t stand having a runny nose, or spilling things. Whatever the reason, I carry a few around with me all the time. I know it’s probably not the best for the environment, but I do buy recycled as much as possible. Anyway, that’s what the black pouch is for. And the large black thing is a padded sleeve perfectly sized for the 11-inch MacBook Air.

bag3

Next up, another bag-within-a-bag. This is the one non-Tom Bihn case I use. It’s a Roocase for the iPad mini. The iPad mini actually just barely fits in it, which is fine. I take my iPad mini with me to meetings, especially first-time meetings with new clients, because it doesn’t create a wall like having a laptop on the desk does. I have also stopped carrying my laptop when I travel for pleasure, so the iPad in the Roocase is all I bring. In addition to protecting the iPad, the Roocase has a side pocket into which I manage to shove a Field Notes notebook, Space Pen, headphones and some business cards.

bag4

And finally… everything else. This is the entirety of what I had in my backpack when I came to work this morning, aside from some running clothes I had also shoved in but don’t really feel I need to show here.

bag5

Look at all that stuff! From top left to bottom right, we have:

  • Two copies of my latest CD
  • Victorinox Swiss Army Cybertool S, which is too big to actually carry in my pocket but an essential tool for tech geeks
  • Another Field Notes notebook
  • Sharpie, Field Notes pen, Space Pen
  • Compact travel power strip (highly recommended)
  • More business cards
  • 1/8″ to 1/4″ headphone adapter (not sure why that’s in there)
  • Novelty fan that plugs into iPhone Lightning port
  • Postage stamps
  • iPhone/iPad charger
  • MacBook Air charger
  • $3.01 in change
  • A bunch of Ricola cough drops (original flavor)
  • Spare keys on a special strap that Tom Bihn also makes
  • Anker portable phone charger, its charging cable, a USB-to-Lightning cable, and carrying pouch
  • Roocase with iPad mini and all of that crap inside it
  • THE BEST BACKPACK EVER
  • 11-inch MacBook Air with padded sleeve
  • Accessory pouch with napkins
  • Accessory pouch with adapters, thumb drives and iPod nano

P.S. Sorry for the quality of the photos… I hastily snapped these on the studio conference table under harsh fluorescent lighting.