Wednesday, March 30, 2016

img tags and baselines

I just wrapped up DesignLab's Design 101 online course - great interactions with real-live mentors.

For my final project I put together a draft to sell my comic So You're Going to Die... my first draft started something like this:



For my second and more or less final draft I started with this rough idea my mentor Charlene Foote sketched out:

The thing is, when I look at it on my computer it was kind of a "cheat", since the boundary of the image was a logical place for the skull to end, but on a webpage, I'd have to figure out what went underneath. At first i thought a pinstripe, but then I finally ended up making the whole bottom a different color:
There was a problem though: the skull there is riding a bit above the div. I could hack it back into place with a position:relative; but that's hardly elegant, but when I was careful to set all relevant padding and margin to, it was still hanging up there?

I think the issue is that imgs are by default "inline", and that's geared to put them on corresponding text baselines. Which is usually a decent default, but the text baseline leaves room for a descender; no good if you're looking to have the image snug with whatever is beneath.

After a little experimenting the simplest solution was making the image display:block; ... inline-block had the same descender issue.

Seems like there's always more to learn in CSS... but especially in js. It's counterintuitive to me how much people can get done with incomplete knowledge... kind of a life lesson, actually.

Thursday, March 24, 2016

the derp of ui

Google Chrome has a profile manager switcher, a little button on the top right of the browser. Seems convenient, but maybe they put the user icon up there, or somehow let me use aliases other than "Kirk" vs "Kirk"? #uifail

UPDATE: I guess there is a way to change it, you can go under Chrome Settings | People and then edit it for the account you're currently using it as.

Tuesday, March 22, 2016

for whom the postman rings twice

For faking AJAX-y requests, Postman is hard to beat. It can do all kinds of thing with request headers and json payloads and what not. I didn't mess with the Chrome app but the free OSX version is pretty keen. I like the logo -- it reminds me of my own comic Young Astronauts in Love -- though it's a little odd they went with a space postman theme.

Monday, March 14, 2016

the art of the grep

At my dayjob they've started enforcing ESLint rules. One of those is that all js strings should be in single quotes, not double.

This seems to be like maybe the wrong standard; for example, assuming your product owner isn't pedantic about "smart" single quotes vs straight quotes, than if you have a string with a word using a contraction, you 'mustn\'t' fail to escape it. (Also I noticed when we grab AJAX payload data from Firefox inspector to shove into a mock, we have to change the double quotes - JSON isn't allowed to use single quotes, only double.)

On the other hand, there's an old tradition where html tends to use " for attributes, so then ' would be safer for javascript that might be in there (err, not that you should be doing that much these days, probably.)

Also, I think single quotes just 'feels cooler' to some engineers. As much as any of those arguments, that's probably why they chose what they did.

And that's fine. The critical thing is to have a standard, since when we adhere to that standard we can do simple cross-file searches 'like this' and not have to re-run them for double quotes, or finagle a regular expression.

The dayjob also use angular translate for localization. It's pretty good, but I've come hate our translation file format, which uses JSON-y hierarchy like this:
{
 SOMEPAGE: {
   FORM1:{
     CAPTION1:'This is form one caption one',
     CAPTION2:'This is form two caption two',
     ERROR:'This is an error message.'
    }
 }

Those are then referenced in the angular html via something like 
{{ 'SOMPAGE.FORM1.CAPTION1' | translate }} 
and in the code something like  
$translate.instant('SOMEPAGE.FORM1.ERROR');

So I think one problem is obvious; once that .js file gets big, it's tough to cross reference 'SOMPAGE.FORM1.CAPTION1' and find it in the file, you have to manually walk down the hierarchy, you can't just do a simple cross-file search for it (some properly configured editors will jump you there though.)

The other problem is: merges can be rather nightmarish. If something happens and curly braces and/or indentation start to get junked up, unwinding that is a laborious task.

The old barbaric way of doing it would be like
SOMEPAGE.FORM1.CAPTION1=This is form one caption one
SOMEPAGE.FORM1.CAPTION2=This is form one caption two
SOMEPAGE.FORM1.ERROR=This is an error message.

So that looks kind of ugly and redundant, but it's ton easier to grep and merge. 

The hierarchy has some advantages, like it does make sure things are grouped pretty well, but mostly I think coders went that way because it's cool, and doesn't look as clunky as the old "properties file" format, or its JSON-ish equivalent. 

Actually the hierarchy thing reminds me a bit of why JSON beat XML... to quote the old Coding Horror blog:
Wouldn't it be nice to have easily readable, understandable data and configuration files, without all those sharp, pointy angle brackets jabbing you directly in your ever-lovin' eyeballs?
In this case, wanting to enforce hierarchy seems pretty parallel to the structure enforcement XML purists crave.

Friday, March 11, 2016

promises, promises

At work I've been learning Protractor by the time-honored method of "pick stuff up on the fly from existing code" without taking the time to sit and read much.

A coworker used the same technique, so together I was able to correct their code... if you're reading from an input element, maybe one selected like this:
this.dealNameField = element(by.model('deal.name'));

You probably want
this.dealNameField.getAttribute('value');

and NOT
this.dealNameField.getText();

(I was surprised there wasn't a convenience function ala .getValue() , akin to what's there in jQuery land)

More significantly, I was harshly reminded that Protractor deals with promises, and if you try to do a lot of poking around with the requisite expect() type code, you're in for a world of confusion.

Also, note to future self,
 expect(widget.alertMessage.isPresent()).toBe(false); 
is a pretty useful construct (where widget.alertMessage was the element css selector thingy)

Thursday, March 10, 2016

cool resource: google fonts

Google Fonts is pretty excellent. I'm becoming aware that the old "holy trinity" of "helvetica,arial,sans-serif" is looking a bit dated, so it's nice to explore some options.

The UI guides you through the steps: you browse the typefaces, click on ones you like to add it to your shopping cart of sorts (keeping in mind each adds a smidgin to download time), click "Use" - if you need bold, you have to select that as a variant specifically (and it will increase download). After that, add the css link to your header and access it in your own css.

Excellent!
(Sorry for all the "quick hits" as of late... especially for stuff that many people already know about. But I post this stuff just in case people hadn't seen 'em, and as notes for my future self...)

Wednesday, March 9, 2016

i <3 sourcetree

Just a quick plug for Atlassian's Git/Mercurial client SourceTree It's a bit like... I dunno, a GPS for git. It took me a while to get a feel for git's multistage local repository model; how an edited file is just there (I think of it as being in a bit of a ghostly state), then you can "add" it, then "commit" it, then finally push it, and maybe then finally finally do a pull request. Having a visual history of branches, and their merges and commit infos, along with all branches locally and remote, and then a third section about the current action... it's so good.

Like with a GPS, I guess there's a chance that I'll be more empowered in general when I have it but less fluent when I don't, but that's a compromise I'm willing to live with, since I can get that understanding of the actual git command line pretty easily when I need to.

Monday, March 7, 2016

google map simplistic example code

I'm really proud of the work I've done on http://jpporchfest.org over the past few years, and I might be helping Brookline get their stuff together- for their first year they might not want to be as high tech as we've been, but I was surprised that I couldn't easily find the work I did to help Plumfest (on Plum Island) assemble their map, so I'm putting this here for future reference: http://kirkdev.alienbill.com/plum2015/

Friday, March 4, 2016

quote on typeface and font

"Typeface is to font as song is to digital audio file."
--Will Ryan. My design class is taking on typography now...

Thursday, March 3, 2016

angular protractor tip: what requests were made?

I'm building up my testing mojo.

One challenge I'm surprised doesn't get talked about more is keeping your protractor mocks up to date as forms and endpoints change - keeping them in sync seems like a significant challenge, especially if you've used the "pluck data from the console network tab, call that the mock data" method - often the state of the system you're using for that kind of developer testing is pretty arbitrary, and might be different if you tried to redo the mock data straight from the system.

I asked about it at work, one developer suggested the test do
afterEach(function () {
    mock.requestsMade().then(function (requests) {
   console.log(requests);
});
});
but that only shows the mocks that were successfully caught; I'm interested in the opposite.

I hunted around without luck at finding the code that intercepts each request (and/or decides to let it pass through if there are no matching mocks) and jamming in some console.log()s. I ended up resorting to doing a browser.pause() or two, opening up the browser's network tab, and doing a visual delta inspection from that. Suboptimal, but got the job done for now.