Thursday, December 29, 2016

the digital library of babel

Jorge Luis Borges introduced the concept of the Library of Babel,  a "vast library containing all possible 410-page books of a certain format and character set." To further quote wikipedia,
Though the order and content of the books is random and apparently completely meaningless, the inhabitants believe that the books contain every possible ordering of just 25 basic characters (22 letters, the period, the comma, and the space). Though the vast majority of the books in this universe are pure gibberish, the library also must contain, somewhere, every coherent book ever written, or that might ever be written, and every possible permutation or slightly erroneous version of every one of those books.
The other day, my company CarGurus had a lunch and learn about the internals of git. I've always been impressed with how quick updates were once you've cloned a repository. In part that's because of how git stores an archive with a compressed version of every version of every file and folder your project has generated, and so chances are in doesn't have to pull down that much fresh data. What's really clever is how it stores them; each is in a physical file named after the SHA-1 hash of the file contents (each physical file sits in a folder named for the first two hex digits of the 40-hex-digit hash, you can see those folders in the .git/objects/ dir of your git project.)

SHA-1 is really amazing, because it's SO amazingly unlikely that two different files will generate the same hash. This page describes it as
Here’s an example to give you an idea of what it would take to get a SHA-1 collision. If all 6.5 billion humans on Earth were programming, and every second, each one was producing code that was the equivalent of the entire Linux kernel history (3.6 million Git objects) and pushing it into one enormous Git repository, it would take roughly 2 years until that repository contained enough objects to have a 50% probability of a single SHA-1 object collision. A higher probability exists that every member of your programming team will be attacked and killed by wolves in unrelated incidents on the same night.
So. Many years ago, an awesome experimental site word.com (now sadly defunct, the domain bought out by Merriam-Webster) ran a subsite called Pixeltime - you can read about it at my tribute page, but the upshot was it was an online graphic editor slash contest with an emcee the Pixel Master whom I've described as "a cross of Mr. Rogers and Max Headroom via Blue Man Group". Each image was 45x45, with a palette of 16 colors. (I made some visual basic hacks that let me essentially upload photos in 5 shades of gray by grabbing the mouse and clicking each pixel)


That one on the right is a little joke - I realized there was a maximum number of images that could be made in that format... at first I badly underestimated how many that is, but it turns out it's 16^2025. (one square could be 16 colors, 2 squares would be 16 * 16, etc) Anyway, most calculators don't even try to figure out what that is, they just call it "infinity".

So here's the thing: that "infinity" is much, much, much bigger than the number of unique SHA-1 hashes. If you were to make a hash for each image, you would certainly get a large number of collisions. In fact, 45x45 is extravagant - by my reckoning you could flood SHA-1 with a simple 16 colors at 10x10, which gives you 2.6 * 10 ^ 120 pictures. (I encourage people to check my math - I've certainly got it wrong before.)

So SHA-1 hashspace is so much bigger than what humanity could conceivably generate, and yet the universe of everything - if you don't put many restrictions on the grammar of the everything you're generating - is so much larger than that.

I don't think our brains can even deal with a million, never mind billions or trillions. (My 6th grade math teacher had a book of a thousand pages of a thousand dots each, with certain amusing values labeled.) Hell, get a dollars worth of pennies, lay em out in an uneven sprawl on a flat surface, and I'll bet you think it looks more like 40 cents.

Or, just watch this:

Monday, December 26, 2016

recreating processing / p5.js's map() function in php (and regular js)

Processing's map() function (here's an interactive p5 demo of it) is super useful and conceptually important, but I don't know if it natively exists in PHP, or I just don't know the term for it.

It takes 5 values, a basic value, the min and max value of the input range, and then the min and max value of the output range. So if you wanted to position something in Processing based on the pointer X position, but constrain it from, say, 1-100, you would call

map(mouseX, 0, width, 1,100);

Note that basic values outside the "input range" are valid, and will result in outputs outside the output range, and similarly you can flip either pair of range numbers and get things reversed, so to speak.

Anyway, I was starting a DIY wordcloud in PHP for tags on my website, and wanted to map the tag appearance count (ranging from 1-250 or so) to font pixel sizes (maybe from 10 to 100 or so).

Since the processing page provided a nice little tester, I wrote it in Java to make sure I wasn't screwing anything up, and could visually compare results to the existing map() function:

float mymap(float val, float inputMin,float inputMax,
    float outputMin, float outputMax){
     float inputRange = inputMax - inputMin;
     float outputRange = outputMax - outputMin;
     float scale = outputRange / inputRange;
     float trueVal = val - inputMin;
     return outputMin + (trueVal * scale);
}

and then ported it to PHP:

function mymap($val,$inputMin,$inputMax, $outputMin, $outputMax){
     $inputRange = $inputMax - $inputMin;
     $outputRange = $outputMax - $outputMin;
     $scale = $outputRange / $inputRange;
     $trueVal = $val - $inputMin;
     return $outputMin + ($trueVal * $scale);
}

Didn't do much error checking, if the min and max of the input are equal I guess that might be a problem.

2020 UPDATE: the PHP code above works verbatim in js! Or to be a little cooler about it, and remove the "$" prefix for variables (even though that's totally valid js)

export const map = (val, inputMin, inputMax, outputMin, outputMax) => {
    const inputRange = inputMax - inputMin;
    const outputRange = outputMax - outputMin;
    const scale = outputRange / inputRange;
    const trueVal = val - inputMin;
    return outputMin + trueVal * scale;
}

Here's the first (well, second, I fiddled with a consistent line-height) result:
Not great, not terrible. I might try something like jQCloud if I want it to look better (not clear to me yet if you can make each word clickable.)

Sunday, December 25, 2016

simple ai

Merry Christmas! Today is the last day for my 2016 advent calendar.

I admit it ends on a bit of wimper, some of the earlier entries were much more interesting. Probably the most entertaining entry was the first, hockeyclaus. It's based on santaskate, which is the very first one I made when I started constructing these in 2009. It's an easy enough game, but not quite trivial, and some people say they just like bully bashing the elves around.

I used a crude heuristic to give the elves some smarts.... essentially I draw a line between the puck and the goal, and then a circle a small, arbitrary distance around the puck. If the puck is further from the goal than the elf is, the elf tries to get to the intersection of that line and circle but on the far side of puck - if the puck is nearer the goal, the elf tries to drive through the puck to the goal, that's the point it's attracted to.

I added a debug feature to the game, hit 'd' to toggle the extra visualization:
In this diagram, you see the lower elf is nearer the goal than the puck is, so is attracted to a point behind the puck, while the upper elf figures it's more or less on the other side of the puck already. Clearly not a good algorithm, but I'm ok with this game not being very challenging.

It might be cool to make this a Comp Sci programming challenge... how would two teams of one or two elves compete, in what is roughly a full-round-arena version of air hockey? I could see making an interface that both fully describes the "world" and all actors in it, and then lets the program say what direction of thrust each player it controls gets... I wonder what strategies would emerge from people who are actually good at programming AI.

drive space and network speeds have flatlined?

This chart, from Matt Komorowski's Cost per Gb Update page, confirms an inkling I've had...
Hard drives ain't getting bigger, the right side of that line is flat. Compare that to Komorowski's 2009 post, when things were a bit more rosy...

I'm feeling this now because I'm been looking for an excuse to replace my 2013 Macbook Air (apparently I'm a masochist when it comes to ports) I had my current model's HD space goosed up to 500Gb when I acquired it. If I got a new "Macbook" and if storage was my major concern over processor speed and memory (which it is), I'd have to pay at $1400 vs $1000 for the base model.

Some of that's the Apple Tax, but they're also an industry pacesetter, and the situation doesn't seem better in PC land. (Not that I consider it a serious option for me right now.)

(Phones have had similar flattenings. Apple finally shook off some its old "16 Gb might be good enough for cheapskates" illusion, but the asymmetry of their storage math, offering models at 256Gb, 128 and then 32 rather than 64 shows that they are playing the game of artificial incentives to not go with the cheapest model.)

And like that first Komorowski link suggests, some of its the cloud, people don't generally aren't storing as much locally as they used to. For me, I feel the pain mostly with photos and videos from my own phone (especially since I've been doing One Second Everyday for a few years) and other cameras - that's what pushes me to want larger capacity on my laptop, I'm old and curmudgeonly enough that I don't trust any cloud service, or any system more complex than "cleverly named nested folders I can see are backed up properly".

But even if I embraced a cloud service - it's not like network speeds have gotten that much better either! Objectively, home speeds feel like they've flatlined as well, and most people don't have unlimited data on mobile.

And Moore's law has hit some rough limits itself; having to be so aware of the quantum is a real pain for chip designers.

After a century of astounding technological progress, and with some of our proudest achievements in space being half a century ago, you wonder how badly things are going to stall. Combine that with a political situation that seems rather retrograde, and it's tough to keep all parts of the the old optimism going...

Thursday, December 22, 2016

gadgets of the 90s

Cool piece on some gadgets (2 organizers and a phone) from the 1990s. I'm so nostalgic for this kind of stuff, and the discussion of the UIs and formfactors and so forth was thoughtful if not particularly deep.

The PalmPilot was the first product to combine the form factor, general UI, and organizer functionality we all enjoy on our slab phones today. (Newton was first, but missed the form factor- though come to think of it, large phones are getting back up there in screensize, but the drive for device thinness is even more critical.

(Link via Lost in Mobile, a great blog for gadget and watch lovers. Of course Shaun McGill is an even bigger fan of the Psion than the Palm, and I can't really blame him. His How Did We Get to the iPhone is a nice read in the same area.)

Wednesday, December 21, 2016

$(document).ready() add how these kids don't know from grep-ability

On a code review with a tad of jQuery, I got dinged for using the old-school
$(document).ready(myFunction);
rather than the new hotness of
$(myFunction);
The former is being deprectated but I really think the recommended syntax suffers from poor grep-ability, you can't readily find all instances of "something that happens when the page loads" across a codebase, or even in the context of a single file, since $(myFunction) is about the same as $(mySelector) and both would require a fancier regex to distinguish usage from $("anotherSelector") or $('yetAnotherSelector').

The problem is that what was the selector for "ready()" never mattered, so this page claims people were using $(), $("document"), $(document), as well as confused people using $("someImageSelector") in the false hope it would wait til the image loaded.

In practice, I only saw $(document) used, but anyway. Progress... Better syntactics, poorer searching.

Thursday, December 15, 2016

chrome's mobile device emulation with the phone around it

Shown: the "before" from an
upcoming redesign...
I guess it wasn't too too many years ago that Firefox's "Firebug" was the web developer's friend, the main way of getting insight into the piecesparts of a webpage, but Chrome's devtools have become the new standard.

One useful part of it is the emulation of various phones and devices, so that sites with specialized mobile modes can be accurately emulated. For one page I also wanted some fake-y "screenshots on phone" with the gadget's hardware bezel etc visible around the sides of the content. It wasn't easy to google for, but eventually I realized at the top right of the bar with the device picker was a "..." menu (except the dots were arranged vertically) and one of the options was "Show Device Frame"

So, just mentioning it here for reference for my future self, or in case it helps some trying to google for it.

Tuesday, December 13, 2016

the return of star ratings to ios

3 months ago I complained that star ratings were dropped from iOS, but as of 10.2, they're back. More or less... you have to explicitly enable them by going to Settings | Music and toggling "Show Star Ratings" (Mystery: why doesn't Settings' find box show anything for "star"? Their search tool is ridiculously limited...)

Once you're there, this option gets added to the "..." menu when a song is playing...

Then it's a pretty simple dialog:

It's distinctly tougher to get to than previously, where tapping on the album cover image would flip the image, and then another tap would set the # of stars and flip it back with no need to hit "Done". People were complaining about the complexity on MacRumors, since setting a star rating used to feel like a more or less reasonable thing to do while driving, and now it's a bit on the fiddly side for that. Overall I think it supports my earlier speculation that Apple's UX folks felt there was too much confusion relative to overlap with the heart-based Like/Dislike options, which feed back into Apples "music selected for you" AI in a way the stars don't - so they'll keep stars around for power users, but for most folks they want to keep them on the simpler pattern.

It's reassuring to see Apple is aware that this is an important features for some of their users. (The earlier hack of using Siri to set the star rating, besides interrupting the playing song, wasn't complete for me because I often I just want to check if I had already advanced a song to the 4- or 5-star level, and Siri wouldn't tell me what a song was already rated) Hopefully this should ensure stars in iTunes will remain for the foreseeable future. (Critical to me because of my use of smart playlists)

Friday, December 9, 2016

javascript30

https://javascript30.com/ - build 30 things in 30 days. Interesting!

freemarker template: safely pass optional freemarker boolean into javascript

New job! I started with CarGurus just this week. Great site if you want to both find cars in your area and know if you'd be getting a good deal or a bad deal.

Interesting culture here - super engineer-centric, features tend to be outlined and handed to coders rather than having a lot (or, any) independent graphic design work beforehand. Plus they have come up with solid answers to problems I've seen plaguing other places I've worked: for example, the way developers too often play with "toy" databases that don't reflect what's going on production. For CarGurus, there are 3 options for our remote dev machines: slice, which is that minimalist subset that is sometimes good to work with on the server side, staging, which is a local weekly copy of production, and shared staging, which is the same but doesn't require everyone to do as much maintenance.

The technology is a mix of proven and reliable and more cutting edge. (Cutting-edge-wise I'm so relieved they're going with React and bypassed the whole Angular thing entirely) On the server, that means some older stuff like Struts and FreeMarker Templating; but both are actually pretty good at what they do. FreeMarker predates JSPs but is a now a well maintained Apache project.

Still, it can be a little arcane. One problem was I wanted to set a variable on the FreeMarker side for Javascript to read as a boolean, but to have the absence of that variable be smoothly treated as 'false'. The code for that turned out to be:

<script>
var isModal = ${(feedbackAsModal?has_content)?then(feedbackAsModal?c,'false')};
</script>

A little wordy but not too bad.

Oh, plus CarGurus bring in lunch for everyone every day, so that's a plus, though I still haven't quite worked out how to manage my calorie counting...

UPDATE:
Senior coworker Jasper suggest:
var isModal = ${(feedbackAsModal!false)?string?js_string};

For me the challenge is remembering that FreeMarker is Java-y in its view of typing, even though it doesn't always look it- it kind of feels like other duck-typed languages I have more familiarity with, plus default variable assignments don't have to specify a type.

As I read through the FreeMarker docs, other idiosyncrasies people here have pointed out include "Freemarker has no default printing of booleans, you need to explicitly use ?string". Also it kinda hates null values - the ! operator is important, in that earlier example, with its meaning "use this substitute if the actual value is null"

Friday, December 2, 2016

advent calendar redux

advent2016.alienbill.com Once again, I made a virtual advent calendar! An original little digital toy for each day leading up to Christmas. You can come back daily to see what's unlocked.

I've been doing these for about 7 or so years. It's a fun way to remind myself that programming can be fun, it doesn't just have to be for work...

I might have started out with the best of the 25, Santa Hockey is actually kind of a fun little game.

Thursday, November 24, 2016

photocap.php : offline photo captioning hack

So, I haven't posted much lately, I was in Malaysia for a bit under two weeks.

One thing about vacations to Malaysia - lots of pictures...

(If for some reason you want to see more, go here and start clicking through up to the 21st)

Anyway, in the current social media world, I tend to double post; I put photo galleries on FB, where friends and family are more likely to see it and comment, but I also like keeping them on my blog as their permanent home.

FB has polished photo gallery editing, but my blog doesn't. Also, where Internet was spotty (like at our resort; downloading was fine but uploading was terribly slow) or non-existent, I wanted a tool to edit captions offline, one that made it easy to later put the photos onto FB and my site. For FB, it's still pretty manual copy and pasting, but it goes fast. (Haven't researched if there are any better ways to automate making albums with captions, but frankly I do it so rarely it might not be worth more dev time.) For my blog I can just generate the appropriate HTML and copy and paste (modulo some search and replace fiddling I do for my blogs way of handling thumbnails and upload folders)

PHP has a convenient built-in webserver, from a shell run 
php -S localhost:8000
(or whatever port you like)

So here's the simple editor I came up with, a one-file-wonder. It has a bit of Javascript that I kept vanilla (I do like when everything can just be one file), it writes out a tab delimited CAPTIONS.txt file, and it stores deleted photos in a folder called "killem".

Below is a link to the code for my future reference, I just need to copy and paste it into a file named "photocap.php" in the same folder as all the photos. I ran into a few PHP quirks, like I had to encode filenames rather than use them as straight up keys because "." is not allowed in a key.

Also the code is pretty rough, but that's what I get for hacking on a sunny beach while drinking...

I published the code at github.

Friday, November 4, 2016

the art of the emoji


MOMA's Paul's Galloway writes The Original Emoji Set Has Been Added to The Museum of Modern Art’s Collection:
I tend to use emojis more freely than some of my correspondents, I think I'm more aware of how chilly of a tone text messages can have without them, or at least some gratuitous exclamation points.

I don't mind yellow-faced smilies, especially when picked from a list, but I'm sometimes bummed the standard is to automatically translate punctuation smilies like :-) into the cartoon version. It takes a semi-clever typographical joke into a very literal thing, and sometimes has issues with expressions from different emoji sets setting carrying somewhat different moods. (Or stuff like Apple swapping the gun for a squirt gun.) Also sometimes I worry that we're regressing into simple pictographs. On the other hand Wired had a guide to some of the way teens were using emoji in somewhat more nuanced ways.

I think you can tell Asia has driven a lot of the Emoji standards (I mean, even besides the name which has supplanted Emoticons and Smilies.) For instance in the 1990s, at least for me
:-) was smiling, and
:-D was laughing
but those are called"slightly smiling" and "grinning" respectively,  it seems, and the laughing involves tears.

One thing I discovered playing Pictionary with Germans is that, even an English, a frown is defined as the gesture of the brow, not the lips ("furrow one's brow in an expression of disapproval, displeasure, or concentration.") Similarly, historically Asian emoticons often emphasize the eyes rather than the mouth- In 2003 I blogged about about some Japanese Smilies:

(^_^)
smile
(>_<)
ouch
(-_-)
fuming
(@_@)
confused
*^_^*
blushing
(^^)//
applause

Those were all ASCII based... as Unicode caught on, of course there was even more flexibility in character-based emoji perhaps reaching it's pinnacle with
¯\_(ツ)_/¯

I do love that guy.

the kingdom of nouns

If you like a good (if old) rant you might enjoy Steve Yegge's Execution in the Kingdom of Nouns.

I've always thought verbs were a bit underrated. Earlier this year I wrote:
I don't care so much about the interior lives of things; people and computer objects alike should be judged on what they do, not what you think they "are". (Conversely, from a Bayesian analysis point of view, what they "are" will influence what they are likely to "do", so getting a handle on what they "are" is better than relying on individual observations of their action.) 
It reminds me of that Geocities-era classic Object Oriented Programming Oversold! - though you need the Wayback machine to see it.

The Kingdom article says
It's odd, though, that Java appears to be the only mainstream object-oriented language that exhibits radically noun-centric behavior
If you read You Have Ruined Javascript, you see Angular giving the radical noun-ism the old college try (admittedly well after the Kingdom article was written.)

Image Capture for moving large files and photos in bulk

Macbooks are getting rid of the SD card reader.  Here's Apple exec Phillip Schiller defending that decision in The Independent:
The new Pros have no SD card slot for a camera memory card. Why not?
Because of a couple of things. One, it’s a bit of a cumbersome slot. You've got this thing sticking halfway out. Then there are very fine and fast USB card readers, and then you can use CompactFlash as well as SD. So we could never really resolve this – we picked SD because more consumer cameras have SD but you can only pick one. So, that was a bit of a trade-off. And then more and more cameras are starting to build wireless transfer into the camera. That’s proving very useful. So we think there’s a path forward where you can use a physical adaptor if you want, or do wireless transfer.
I'm not sure I buy the "cumbersome" argument; when not in use it's recessed, and when in use, well, every other port has a big old wire sticking out of it, so I don't see it as a real point.

I find the SD card a great method of generalized file transfer and backup, not just a tool for getting photos off cameras, and it was convenient not to need the reader, though they're cheap. But, just another dongle - dongles which will likely be the way of your world for the next two or three years if you upgrade your Mac or iPhone.

Of course, some of the SD Card indifference is justified because so much amateur photography is done by smartphone now anyway. (Which is probably the strongest pitch for "it's wireless now", camera to wifi last felt really clunky and gimmicky to me, though maybe I'm out of the loop with recent advances.) Still, I find wireless transfer slow, and in my curmudgeonly oldness, I have a strong preference for dealing with photos as regular files and not being beholden to some service for another.

So as a reminder, Macs come with the "Image Capture" app, which I think is the fastest / simplest way of getting photos and videos off of iOS devices in bulk.

Incidentally, I learned about that quote from Shaun McGill's excellent Lost in Mobile blog. 
 His stuff has been through several models seeking a business model, but it's always a great view of modern consumer tech. (And I've always liked his How Did We Get to the iPhone? which traces through the PDAs and the like that provide the evolutionary backdrop for that 2007 wonder.)

Saturday, October 29, 2016

good ol' rsync

Among other backup strategies for my laptop (including, frankly, moving a lot of important stuff to Dropbox, despite the minor security concerns) I like doing some file syncing "the old fashioned way", manual copies to a plugged in USB drive.

I had to interrupt a copy of my main "~/data/" folder though, and didn't want to take the time to start another full copy, so I googled and was reminded of rsync:
rsync -av /source-path/source-dir/ /other-path/dest-dir/
as the stackechange page I cribbed that from reminds me, assuming you want "dest-dir" to have the same contents as "source-dir" make sure both the old and the new paths keep their trailing slashes, otherwise you might be off by a level.

Tuesday, October 25, 2016

low contrast ain't so easy on the eyes

How the Web Became Unreadable - the tl;dr is that too many sites are using gray text on somewhat lighter gray backgrounds - that in theory this makes thing "gentler" on the eyes but for many just makes things harder to read. My comment was:
I have sympathy for people who struggle with what is almost certainly a designer trend kind of thing, done just to make a page feel a bit more hip. I’m crossing my fingers that the trend doesn’t take a cue from AMOLED-tuned screens and start putting light text on black or very dark backgrounds; for many people with astigmatism, that’s a recipe for dancing afterimages everywhere. (To the extent that sometimes I “Select All” text on a dark site in the hopes that the selected text background is a more balanced color.)
So, here's hoping!

Tuesday, October 18, 2016

php. for reals.

From Taking PHP Seriously:
Most programmers who have only casually used PHP know two things about it: that it is a bad language, which they would never use if given the choice; and that some of the most extraordinarily successful projects in history use it. This is not quite a contradiction, but it should make us curious. Did Facebook, Wikipedia, Wordpress, Etsy, Baidu, Box, and more recently Slack all succeed in spite of using PHP? Would they all have been better off expressing their application in Ruby? Erlang? Haskell?
I think it's a great defense of the platform. I think so many developers underestimate things because they don't feel "engineer-y" enough. Bespoke complexity that grows up because the tools were too simplistic for the task at hand is not always that much worse than the complexity of opaque systems that are hard to debug. Transparency (in this case, the ease of following codepath execution), accesibility/ease of setup, tight code-run loops, having a ton of baked-in utility functions without pursuing versioning hell... these are great things.

Friday, October 14, 2016

if your nose runs and your feet smell you must be umopepisdn

Less-than-earthshaking update:

Playing with the look of this blog. For a long while I just had it mirror the oversized image of alienbill.com. Now I'm mirroring the starkness of kirk.is, but I'm not sure it's really working.

Anyway, keeping notes on day-to-day things is crucial for most developers. For a few weeks I've tried a new angle on it, a single note in Evernote (I generally prefer the minimalism of Simplenote, but I use that for my personal stuff and like keeping the work stuff separate) called the "UPSIDEDOWN LOG". I'm experimenting with reverse chronological order (even for intraday additions), I just like how the past recedes into the distance and I don't have to scroll to the bottom all the time to add new stuff.

Monday, October 10, 2016

itunes store search: "100 matches ought to be enough for anybody"

Back to being "Kirk's UI Gripe Blog"...

Man, iTunes store search is so pathetic. Supposedly a while back they had a power search mode, but now it's just keywords. You can't search for just a song title, for instance, you're going to get any artist or album who has the same name. Even better - their version of "All Results" cuts off at 100. So if there are over 100 non-title matches for a song you're trying to find a good cover of, and the song's title is later in the alphabet, there's no way the song you're looking for will show up on the list.

Even more insulting is the message after those 100 items:
"Less relevant items are not displayed. To narrow your results, use more specific search terms."

I would if you'd let me, jerky.

Friday, October 7, 2016

fixing wordpress plugins

Yesterday I had a venture in the extraordinarily un-glamorous world of Wordpress.

A friend accidentally "white screen of death"'d her company's site. Apparently, it can be a really bad idea to hit "Update All Plugins" (maybe especially if you are running an older version of PHP? Not quite sure.)

I admit, I'm a better developer than admin, which was that this called for.  Still, I decided to give it the old college try.

I was grateful that the shared GoDaddy site still offered normal ftp and better yet, ssh access.

I saw there was a boiler plate Wordpress index.php. Oddly I could run "php index.php" from the shell and a more or less normal looking site was generated. So after putting the regular index.php safely aside,  for a while I replaced it with the content of running php in the shell... not perfect (both in terms of missing theme and showing bare [plugin] slugs) but better than a blank screen or a "Under Construction" link.

What To Do When A WordPress Plugin Causes An Error was a helpful link. Things were so bad that the plugin admin page was also white screening, but I admire how hackable it is... each plugin was represented by a subdirectory in a general plugins folder - and to deactivate a plugin, you can just remove there. We did that, and the admin page returned (as did the main functionality, so I put the default index.php back) Then, you can put all the plugin folders back, but, oddly, but usefully, they're all deactivated. At that point we turn them on one by one (making sure we knew which directory entry they corresponded to - usually it's obvious but in a few cases we had to click on the link), found the one that was killing stuff, and left it out.

Anyway, I appreciate how Wordpress has a lot going on, but you can still follow the logic...

Thursday, October 6, 2016

amazon deploys new software to production every 11.6 seconds

At my work's devfest, I learned that Amazon deploys new software to production every 11.6 seconds. This video describes some of the history and the infrastructure patterns that support that:


What astonishes me the most (not that the video gets into it too much) is how decoupled everything must be to make that work; they must have some brilliant way of handing versioning and/or handoff as a user crosses from one application to another.

Tuesday, October 4, 2016

an ecosystem out of control

Great Medium piece, How it feels to learn JavaScript in 2016. (It has a link to a reddit discussion where I found some like souls.)

It really is out of control. And that article catches the intimidation factor of it all.

I was never good at foreign language, which I attribute to my poor memorization skills and how language tends to be taught in the USA. But I had a motivation problem: every other class I took in high school and college offered to teach me something new. Foreign language was just new names for everything old. (I accept that if a learner keeps at a language until they internalize it, they will likely be rewarded with new outlooks and ways of thinking--to quote the poet Jack Gilbert "A man said no person is educated who knows only one language, for he cannot distinguish between his thought and the English version." -- but my lack of language chops keeps me far from that kind of rich understanding.)

Anyway, that's what this new ecosystem feels like, new words for everything old. In 1996, discovering Perl CGI was empowering; ditto jQuery and modern CSS in 2010. But this stuff? So little of it really lets me doing anything new. Some of it is more concise, sure, but that brevity is just a veneer over giant swaths of code I'll never understand, and god help me if I screw up using the framework-flavor-of-the-month and have to backtrack to what I did wrong... bespoke code certainly invites complexity, but at least it's YOUR complexity.

Some frameworks do offer new functionality impossible in the old world, like server-side rendering that might help with speed or webscrapers, and some toolkits pull their weight for stuff like running tests. And I certainly find some frameworks (like React) more appealing than others (like the client-side JSP taglib nature of Angular) but overall, I wish more developers would think about how hard it is to keep track of all this stuff, and prefer simplicity, ease of mental-modeling, and transparency to coolness and "power".

(See also: The State of JS survey. Really interesting seeing what things have a high "have used, would not use again" rating. Most notably for me, Angular 1.X)

Sunday, October 2, 2016

industrial design!

O'Reilly's Understanding Industrial Design is pretty hip; a high level overview of the history of industrial design and some implications for the more virtual arts.  The chapters a history, then go into the topics centered around the goals of being sensorial, simple, enduring, playful, thoughtful, sustainable, and finally beautiful.

It seems to be on hiatus from its daily update schedule, but the site Little Big Details, mentioned the books, seems awesome... I love that stuff, and I think finding low-hanging fruit is something I do well.

Good quote cited in the book:
"Less isn't more; just enough is more."
-Milton Glaser
Finally, in the playful section the book mentioned Naoto Fukasawa's clever tea bag marionette:




 "This concept comes from the motion of dipping a tea bag in hot water, which reminds him of a marionette dancing. The handle on this human-shaped tea bag looks like a marionette handle too. When the bag is dipped in hot water, the leaves swell to fill the bag, creating a deep-hued roll. Repeating the dipping action, the user is engaged in a wondrous world of puppet play. Thus, design intrigued with the unconscious emerges through the medium of an action."

Wednesday, September 28, 2016

the engineer vs the designer

I feel like my development draws from two sides of me, the engineer, and the designer.

The engineer part of me wants to say "come on, arial,helvetica,sans-serif, and maybe a courier,monospace - that's all you need. Oh and maybe Impact sometimes, for flair". The designer knows better.

In theory, the designer part of me should be advocating for "proper" quotemarks, the ones that curl around, vs those inch and foot marks that are so much easier to reliably type. In practice, I don't care all that much. And the UX part of me teams up with the engineer in me to DESPISE when they are autocorrected, especially when pasting. It makes sharing code in certain chat programs (I think Hipchat may have had that issue but I don't remember seeing it in Slack) or even recording stuff in "Evernote" problematic.

Actually, Evernote, like a dozen other programs, tries to preserve typefaces and font sizes and colors, sometimes background and foreground. How often does that help? I see its utility SOMETIMES, but should for paste default really be to make everything look like a goofy ransom note? There are some conventions that some programs follow - add a shift to cmd- or ctrl-V pastes "special", and often stripped down, but it's not consistently followed - and again, I'm not convinced it's a smart default especially when "remove formatting" isn't always readily visible.

Monday, September 26, 2016

flywaydb

Flyway seems like a pretty cool way of keeping databases up to date. At work one project uses it and tasks like "flywayMigrate" that takes any new untimestamped .sql files, timestamps 'em, and then runs 'em in sequence. I remember Enpocket used a homebrew system that followed similar patterns.

Friday, September 23, 2016

quick fb ux observation

A friend of mine posted some old high school photos, including some with a very distinctive "laser" background, characteristic of the 80s/90s. About five different people commented something along the lines of "look at those lasers!"

FB made an interesting choice by only displaying comments from people you're friends with inline when browsing on your main feed, but still having the "Write a comment..." box there. People are more likely to see some comments, not realize they haven't seen them all, and then make an "obvious" comment that otherwise they would have just "liked" had they seen it made by someone else.

Thursday, September 22, 2016

sweet css spinners

Cool CSS-only spinners / throbbers / loading widgets... I definitely want to up my understanding of CSS animations, my mind still goes back to controlling CSS properties with jQuery.animate()... and various easings

power devtools in chrome

Twelve Fancy Chrome DevTools Tips - it's funny how Google Chrome has become a defacto development standard...

Tuesday, September 20, 2016

note to self: connection to SQL databases

Looking around for a client to connect to Oracle DBs, SQuirreL SQL Client seems ok. Both the site and the app are rather late-90s in appearance but seem to get the job done, at least once I downloaded the Oracle jdbc jar into /Applications/SQuirreLSQL.app/Contents/Resources/Java/lib/ojdbc7.jar

o sh*t

http://ohshitgit.com/ has a small list of save-your-butt techniques when you screw up in git.

Thursday, September 15, 2016

user gripe: no musical star rating in ios 10

So, my current least favorite misfeature of iOS 10? The Music app no longer supports viewing or updating the "star" rating of a given song.

Previously you could tap the currently playing album cover and it would flip, revealing a simple interface to control the rating. With iOS 10,  the album cover doesn't do anything, but there's a "..." menu that lets you do a "Love" (heart) or "Dislike" (heart crossed out). You can tell Siri to apply a rating to the currently playing song, but I couldn't figure out a way of getting her to tell me what the current song was rated (other reviewers complain more about having to interrupt the current song playback in order to activate Siri and change the rating.)

I can almost hear the UX researchers defending this decision. "Users were getting confused about the difference between star ratings and heart/no heart!" "The hearts so much simpler, and more integrated to the Apple Music service!" "Do you know how few users actually USED the stars? [insert blah blah blah statistic here]%!"

And fair enough, the number of people who will miss this star access, or even star access if they drop it from the MacOS iTunes app, is likely a lot smaller than the number of people bemoaning the headphone jack. Apple is brazen in dropping features in the name of simplicity.

When I first ripped my music in 2004, I rated all of my 2000+ songs from 1 to 5 stars - admittedly this breaks the Don't Give Your Users S**t-Work guideline, but first and foremost it let me decide which songs  I wanted to include in the limited storage space on my device. (I'm definitely a "singles" guy, most albums consist of 2 or 3 songs people want to hear, and a lot of filler.) 3 stars were good and worthy of inclusion, 4 star songs I was psyched about, and 5 were my "most favorite ever". (Later I just got rid of the 1 to 2 star songs even on my desktop.) Apple smart playlists were a great way to manage my music into good/better/best.

For a long while I managed all my music on my desktop, not the phone where I do all my listening - then for a time I tried downloading straight to phone, but got into weird issues with the library on my desktop. So I guess I'm back to the desktop - and even if star management goes away from iTunes entirely, I could get 80% of the effect by manually juggling regular playlists -- the silver lining would be providing the excuse to break my dependency on Apple for acquiring music (before they dropped the DRM I was using Amazon for MP3s, and it seems like they have a better selection anyway.)

Ah well, I'm just a cranky old wanna-be poweruser. So many people prefer streaming, which I just don't get. It eats up bandwidth, you may have to juggle online/offline stuff anyway, and you have to KEEP paying rent for access to "your" music... or maybe it's about my relationship to music, I like to build a familiarity with specific songs so the appeal of the "custom radio station" paradigm for music is something I only understand in my head, not my heart.

Wednesday, September 14, 2016

timezone'd

Time zone support in iOS' default Calendar app is missing one feature: to set the time zone for an event, and then see displayed as it will be when the user is in that time zone.

For instance, if I'm in Boston now and traveling to Dublin next week and have a 10AM meeting scheduled there, does it really make sense to have that display as a 5AM meeting until my own time zone changes?

There's a "Time Zone Override" feature that I thought could fix this, but no... that would just let me see an event relative to Boston time no matter where I was and what I had the time zone set to.

It's a fraught issue with lots of UI/UX edge cases, but I think the best option would be to have a default setting of "assume I'll be in the timezone of future events" that can be overridden on a per-event basis (like if you're scheduling a video call across timezones, and want to know when to get online even as the time is set by their standards) and have a little tag like "Dublin time" for events that are being displayed with the assumption that you'll be at that timezone then.

And of course, shared calendars take even more finesse to get the user's intention across...

Does any calendar app handle this really well?

ios 10 quick thoughts and the mess o' settings

Put iOS 10 on my iPhone 6.

The most in-your-face change is that "slide to unlock" is gone - it's been there since the original iPhone (and survived a little minimalism mishap in iOS7) but now it's "press home to open". Long time users may have to retrain their muscle memory.

It does feel like that home button is getting overloaded - click to unlock, or maybe thumbprint to open, long hold for Siri, double click for running app cards, double touch (not click) for reachability, and then good old click to get back to the homescreen.

(There's a "Home Button" Settings menu with a "Rest Finger to Open" that made the navigation when using Touch ID a lot friendlier - having to alternate between click and fingerprint reading kinda stunk. Not sure why it's not the default.)

My favorite change is the new set of keyboard sounds. Rather than having the same click for every key, normal keys, white space/shift, and delete all have different sound effects. The result is a delightful little blurble that gives subconscious feedback about what keys you're hitting, very pleasing in an ASMR kind of way.

I do think iOS settings have gotten out of hand. A few versions ago they added a search box for it, but it's still a hot mess - making it worse, it only search the top level - like, the Calendar app has a "Time Zone Override" feature (more on that later), but you can't find it by searching "Time Zone".

Anyway, I suspect they got rid of "slide to unlock" so that they could make the quick operations easier - the widgets that are to the left and especially getting to the camera. (Wish I could find a setting for what mode the camera starts in, One Second Everyday geeks like me almost always are diving straight to video...)

Tuesday, September 13, 2016

on assistive touch

Gruber on the New iPhones. He spends a bit too much time about the body material and a fair amount about the camera but them goes into a fascinating digression about how iPhones' physical home button is used differently in different international markets. Certain markets (many in Asia, and Brazil) have gotten the idea that the home buttons wear out (not entirely unjustified, at least for older models) and so it's very common to enable AssistiveTouch, Apple's accessibility tool that launches a popup menu allowing one-touch access to various places, including the home screen.

Its resting state is a very translucent button that can be respositioned, but then anchors on the nearest screen edge. Tapping the button opens up an overlay menu:
(This kind of shared cultural idea about how to use a device (and one not grounded in true assumptions about the device) reminded me of people who are taught that it improves performance to closeout unused iOS apps, and sure enough Gruber moves on to that as an example.)

Anyway the AssistiveTouch button that's always floating over the rest of the UI (but one that's curiously camera shy, it fades out before a screenshot) seems odd to me, a bit intrusive to the UI of the other apps, but I'm probably overthinking it.

Gruber's dive into the subject was in the context of the physical home button, which has shifted from physical clickiness to haptic feedback (a loss, albeit small, in his reckoning) and who knows what the next generation might have, if the Apple designers reach that goal of "front is a single pane of glass". I've always praised the single home button, it's such a centering thing, a way of hitting reset and heading back to the top of things, like the convention of having a websites' name at the top left be a clickable return to the top. Palm had the same idea, though they used a "silkscreen" button and kept their physical buttons for the apps. (Also, for nostalgia purposes I recently bought an original series Pilot... I was surprised that the Application menu didn't take up the full screen, but you could see the last app peeking out from behind, at the top of the screen - so it didn't have that feeling of "homescreen as a place" that I thought was crucial to the experience.)

One final smart thing about AssistiveTouch is it follows the paradigm of "do one action, then return to resting state" that Reachability (double pressing the home button slides the whole iOS screen down allowing easier thumb access) uses. Click-then-go-back is a smarter concept than some of Samsung's (early?) attempts at similar hack to deal with oversized screens, one that would just put the whole system in a only-use-part-of-the-screen mode, and keep it there.

kottke redesign

Fairly recently (a time value representing an increasing number of years - four years used to be a gulf of time enough for the entire High School or College journey, 20-25% of my life 'til that point. Now the percentage is significantly less... but I digress) I started reading kottke,org. Its design felt kind of timeless and was an inspiration for my minimalist kirk.is makeover:

but as his 2008 decade retrospective shows, his site has undergone multiple makeovers. He says his favorite was this:

Anyway, it's a great site with an excellent Signal/Noise ratio. (Also funny to think that I've been doing daily updates to my site for nearly as long, since the tail end of 2000.)

Thursday, September 8, 2016

pantsuit! a ui library for the clinton campaign

Medium piece on Pantsuit: The Hillary Clinton UI pattern library.I hadn't heard much about SMACSS (Scalable and Modular Architecture for CSS - reminds me of the Blues Brothers' nemesis SCMODS - State County Municipal Offender Data System) and ITCSS (Inverted Triangle CSS)

In some ways it ends up looking like the "bad version" of Hungarian Notation, with CSS class prefixes ".c-", ".t-" etc used to indicate "component-based", "theme-based", etc. Also some good stuff on inclusivity.

Wednesday, September 7, 2016

the tenth anniversary of the facebook news feed

Facebook’s News Feed Turns 10. Quote:
At first, people hated it. But much as they complained, Facebook’s data logs suggested they came around quickly. The News Feed caused more people to spend more time on Facebook, a trend that picked up speed during the years that followed. Meanwhile, nearly every other social web service, from Twitter to Instagram to Pinterest, adopted the format.
I always thought Facebook followed Twitter, but I guess Twitter was still in the phase of primarily using being an SMS-based notifier in 2006. I wrote about the power of the stream a few years ago (curious I didn't talk about RSS, though that's never been a huge player.) The ability to assemble a page from a bunch of people likely to write stuff you find interesting generally overwhelms the old individual blogosphere, and in fact only the most diverse news websites seem able to maintain an audience to their separate front page.

FB's curation seems unique to me; I think that is the most underappreciated feature of the site. It's much maligned. On other sites, like Twitter, users protest loudly whenever that service fiddles with its traditional "posts from everyone I'm subscribed to, in the order things were posted" model and the service backs down more often than not. On FB, people also pine for a simpler model, but their cries are generally unheeded.  I think most users don't realize what a fire hose an unfiltered set of posts from all their "friends" would be.

Actually, for me Twitter suffers from the same fire hose effect, and so I pay less attention to it. (Also, the 140 limit used to seem cute and pithy, but now feels so confining.) I tried using Twitter lists to get a more limited subset of posts, but those listss are oddly downplayed in main Twitter web UI. And anyway, it fails pretty hard in Zacho Holman's Don't Give Your Users S**t Work kind of way; having to keep up to date groupings of all your contacts is laborious.

Tuesday, September 6, 2016

react 101

For grins I fired up React, went through its nice tutorial.

I'm trying to think about what I feel about it. It feels nice and clean relative to some other things, and I dig that it's a library and not a framework; it does what it does very well. On the other hand, I'm not always convinced what it does is worth doing, namely, it seems like a lot of engineers really hate working directly on the DOM. But, I think I haven't dug far enough to get into React's sweet spot, and many people like it a lot better when they combine it with its Flux implementation "Redux".

Anyway, I decided to practice what I had studied with a simple helper toy (I'm rearranging the physical folder layout for the domains I host on my server, a lot of fiddly bits to keep track of)... to get there I decided to recreate the classic Angular "hey you synch up a text input and its display with no code!!!".   Here's a fiddle I spun off their Hello World that does that.

var Angularish = React.createClass({
getInitialState: function(){
    return { site:'foo' };
  },
  updateSite: function(e){
  this.setState({ site : e.target.value});
  },
  render: function() {
    return <div><input value={this.state.site} onChange={this.updateSite} /> {this.state.site}</div>;
  }
});

ReactDOM.render(
  <Angularish />,
  document.getElementById('container')
);

I dig that React is very event based; I think a lot of other toolkits rely too much on shared memory and watches and you never know when anything is happening. On the other hand, like all these toolkits it's so very finicky with the syntaxes it introduces; the JSX bit (the little html/XML tag like thing) had to be a properly closed tag (even singletons, in the xhtml sense), a tag value has to be either a string or an {expression} and not a mix, etc, and I had to learn you can't just modify this.state directly.

(for my personal future reference here's the https://jsfiddle.net/sfh7ydpw/1/ I made with more detailed steps for the refactoring; I guess revealing the old and new folder structure isn't much of a security risk.)

2018 UPDATE

Guess it's too much to hope that 1 1/2 year old code would still work.
Here's the updated fiddle: https://jsfiddle.net/69z2wepo/171740/
class Angularish extends React.Component {
constructor(props){
  super(props);
    this.updateSite = this.updateSite.bind(this);
    this.state =  { site:'foo' };
  };
  updateSite(e){
  this.setState({ site : e.target.value});
  };
  render() {
    return <div><input value={this.state.site} onChange={this.updateSite} /> {this.state.site}</div>;
  }
};

ReactDOM.render(
  <Angularish />,
  document.getElementById('container')
);
That's closer to the example presented in https://reactjs.org/docs/lifting-state-up.html
That seems like a surprisingly large amount of shitty boilerplate, tho... this.updateSite = this.updateSite.bind(this); is sort of uncool.

build your own bot

In the "to get to, someday, when I get a good idea" - How To Make a Twitter Bot in Under an Hour

Monday, September 5, 2016

the power of Sass

When doing basic website and web application stuff, my instinct has been to always keep things as "close to the metal" as possible. Basic html5, CSS, and javascript (especially flavored with a bit of JQuery and/or Handlebars) is pretty expressive - it's not like someone in 1994 saying everything should be in assembly language. In this view, it's terrific to have fewer layers to dig through when things don't act as expected.

A smart friend and ex-coworker of mine, Marco Morales, once mentioned that he really liked CSS preprocessors. I asked if he could put his finger on why - I wish I could remember how he put it, but my paraphrase is that he found that it let him speak semantically vs syntactically; he could more readily express his intentions in code.

Currently I'm doing a mini-project in Sass to get a feel for it. Skimming through the intro page gives an idea of what it offers. Variables are kind of a no brainer, for color definitions alone (and font families and the like). Nesting is my second favorite; it feels elegant to have the layout of the stylesheet mirror the structure of the DOM (though you have to be careful to think in terms of reuse, you can kind of get over-specific if you're not careful.)

Also, even if you're not using gulp or grunt, you can easily set up a watch to autotranslate your .scss into .scss - and you get a ".map" file to boot, which lets Chrome point you at the rule in the .scss file directly. The latter behavior removes one of my strongest reservations; when you're poking around in the DOM inspector, you don't want to have to manually/mentally unwind the raw CSS back to the actual code you wrote.

BONUS SASS MIXIN:
The <nobr> tag was an early "find" of mine, to make sure a string of text was kept on the same line. Of course, that kind of non-semantic instruction belongs in CSS, not markup...

@mixin nobr() {
    white-space: nowrap;
}

gets the job done, and then a CSS class can say

@include nobr;

Maybe it's not much more convenient than remembering white-space: nowrap; but to a grizzled web veteran such as myself, it's more concise.

Friday, September 2, 2016

note to self: lodash assign();

It wasn't clear to me what the advantage of
_.assign($rootScope.creative, { somejson: ‘map'} );
was vs
$rootScope.creative = { somejson: ‘map’};

What's going on in the first case is actually a merge; useful if $rootScope.creative already existed with some keys, somejson would be a new key in it. (or any old value of somejson would be replaced with 'map')

Learn something new every day! Some days, two things!

Tuesday, August 30, 2016

note to self: node, nvm...

Note to self, when I'm running functional tests (for our Angular 1.X app suite) and see an error like
const builder = require('./builder');
^^^^^
SyntaxError: Use of const in strict mode.


I'm probably on the wrong node version. "nvm" is what controls that, and hopefully by using "nvm alias default X.X.X" I shouldn't see this again.

(bonus... looking into how to test validators that reject or resolve the defereds from a $q defer()

promise creativeCreateService.validators.impressionTracker3('http://foobar.com');
expect(this.unwrapPromise(promise)).toBeTruthy();

promise creativeCreateService.validators.impressionTracker3('https://foobar.com');
expect(this.unwrapPromise(promise)).toBeTruthy();

promise creativeCreateService.validators.impressionTracker3(_.repeat('A',20));
expect(this.unwrapPromiseRejection(promise)).toBe('Impression tracker must start with http:// or https:// if provided');

the code that supports it is:
    self.unwrapPromise = function unwrapPromise(promise) {
        var value;
        promise.then(function (result) {
            value = result;
        });
        self.$digest();
        return value;
    };

    self.unwrapPromiseRejection = function unwrapPromiseRejection(promise) {
        var value;
        promise.catch(function (error) {
            value = error;
        });
        self.$digest();
        return value;
    };

 )

Saturday, August 27, 2016

the old days of the java plug-in

A while back Gizmodo posted Rest in Hell, Java Plug-In.

It's really too bad it was such a security problem; back before html5 and canvas and powerful javascript, or even before Flash and Shockwave, it really let developers share interesting stuff, much more interesting that what a browser could do alone.

Flash and Shockwave always felt and looked more polished though, both in terms of plugin management and in terms of the end product. Almost all serious Java programs looked a bit "off".

Thursday, August 25, 2016

code katas

Interesting programming exercises: Code katas.

vanilla is the finest of the flavors

This article encouraging starting with "vanilla" javascript intersects with some of my own preferences.

There are some things that are worth not doing from scratch: templating, routing, testing, etc, but even then there's a lot you can do with special purpose libraries rather than overarching frameworks. You then get the pleasure of debugging in a code base that solves just the problem at hand, and is generally bespoke and with business-logic-mirroring stacktraces.

That said, I'm surprised how much one can do while still missing huge swaths of basic Javascript! Take a look at the docs for JS's "Object"... there's more there than you might think - stuff like the prototype chain, the getters and setters... you can go a long way and do a lot of things without realizing they're in there... but then when you have to read someone else's code that uses them, you should be aware.


git 101: rebase from master, squash, etc

I prefer to use SourceTree for git access, and admittedly have generally been leaning "just enough to get by".

I was generally "pulling" from master periodically when working on a story branch, but was introduced to "git rebase master" which does a better job of it - your commits are more your new work, not just a record of the the commits as you kept up with master.

This link has some more about the squash option (like if you do "git rebase -i master"- this will fire up whatever editor you have on git, with lines showing you the commits separately, as "pick" - you have the option of changing all but the first "pick" to "squash" or "fixup" which essentially is saying "treat all these commits changes as one big commit). Once you close the editor, the editor will open again but with a place for the actual commit message you want to include.

I'm not sure what the benefit of squash-ing i, except keeping things a bit neater downstream, or if you have to rollback.

UPDATE: once you do this you have to do a "git push --force-with-lease" since you are rewriting history

Sunday, August 21, 2016

the ugly american

I was in Ireland last week, and noticed that FB must have fiddled with their iconography again; the globe icon was quite a bit odd looking. (An I mean, isn't a globe for "Notifications" a little odd anyway?)

Not going to mention how long it took me to figure out the problem. Forgot that i was so Americas-centric in my outlook!

Sunday, August 14, 2016

imagemagick's mogrify to fix ios exif image rotation issues

Digital Photography Circa 1996 -
cyberpunk gargoyle!
A while back I grumbled about what a hot mess EXIF handling was - how iOS photos tended to always store photos line up with the cameras lens and ignoring orientation for the raw data, but then putting in an EXIF header about how the viewer should rotate it, and some browsers did that, and others didn't and it was generally gross.

At some point in the past I found the fix, but I didn't post about it 'til now- maybe I was holding off 'til I could check it working across different browsers, but I haven't seen an issue for a long time, so-
mogrify -auto-orient imagename.jpg
does the trick.

Sometime in the last year or two I made my blogs upload system both resize the uploaded photo to the appropriate width, as well as store it at original size. Wish I had done that years ago, it really lets my blog be a better archive.

If you like seeing a subjective history of digital photography, starting July on my blog (16th or so) and ending today I've been posting a "dozen best photos of the year"... it's been satisfying kind of mentally revisiting those years, getting back some lost time.