Monday, July 28, 2014

angular edit-in-place

http://jsfiddle.net/joshdmiller/NDFHg/ is a decent little angular.js "edit in place" - i.e. it's a span, click on it for an edit box

Sunday, July 27, 2014

the joy of exif

This is just a rant. I hope to do a followup post once I fix the damn problem.

Man, EXIF and iOS and browsers == bad, bad news.

So, iOS doesn't bother to actually rotate a JPG when it stores it in memory, just notes which way the camera was held in the EXIF metadata, and sophisticated display programs do the right thing to show you your image right way up. Fair enough, I guess, rotating big chunks of memory is hard work for a device.

BUT -- Chrome Safari and Firefox ignore the EXIF when it's a jpg in an img tag, so the images appear at all kinds of random orientations, but then they respect it when you open up the image by itself in a tab. (!!!) IE just always ignores it. So points for consistency for IE.

http://alienbill.com/kirkdev/exif/raw/view.html if you want to see this wonderous magic for yourself.

I was all psyched about my this drag and drop image upload library I found (  http://www.dropzonejs.com/ ) but now I have to figure out how to get ImageMagick to fix this crap before I can enjoy the fruits of my labor. This is really horrendous.

UPDATE: an uncool and limited but dead simple and effective for my needs solution is to open up the iOS image in OSX Preview and hit cmd-S for Save. The resulting file I can then drag right into my dropzone.js-based UI.

BETTER UPDATE: the secret is to use imagemagick's mogrify -auto-orient command - see this blog post for more.

salvaging old laptop HDs

PROTIP: If you have an expired PC laptop and want its harddrive (either for retrieving files or for cheap disk space) you can get a USB enclosure for small money. This one runs about $7 and comes with everything you need, even the USB cable and tiny screwdriver.

Saturday, July 26, 2014

tree - nice recursive directory lister

There's a useful Terminal command called "tree" that you can easily install on a Mac (if you have Homebrew installed, at least.) It's like a variant of "ls" that produces a nice hierarchical view of a parent folder recursively on down.

If you have brew, just type

brew install tree

And there you have it.

PROTIP: you can also tyoe

brew list

to see what software has been installed using it.

Tuesday, July 22, 2014

parkie, the power of simple javascript

Years ago I lived in a neighborhood in Boston that had annoying alternate-side parking rules: something like the 1st and 3rd Wednesday had street cleaning on the right, so park on the left, and the 2nd and 4th Wednesday was the reverse. (I guess this was defined more in a "even/odd #'d side of street" kind of way, but the street was one way, so left/right made more sense.)

It was a fiddly thing to deal with... recalling the date, figuring out the date of the next Wednesday, figuring out which Wednesday of the month it was, remembering which side that implied, etc so I made a Javascript page for it: http://kirk.is/tools/park/ . Super minimalist, it just does the thinking and prints the results, but it "shows its work" so to speak so you can see the reasoning and confirm it for yourself.

My cousins now live in that house, and I revived it (and updated, the day of the week had changed, actually) and gave them a shortcut to the page on their iPhone's homescreen. (In theory I could also have made it a Bookmarklet, which would let it work "offline", though I don't think you can put those on the homescreen, and it's not like these phones are offline that much anyway.)

I like tiny bespoke projects that make life notably better. (This one reminds me of the kind of programming people would do in BASIC on old 8bit computers, but modern portable tech and ubiquitous networking make it much more convenient!)

Friday, July 18, 2014

semi-opaque backgrounds without semi-opaque control

My company did a Hackmatch/Hackathon last night. I ran a one-man team converting a dynamic Excel spreadsheet (meant for helping a scrum team plot out its hours and make commitments) into a one webpage app; partly for me to practice Angular, partly because I'm now scrummaster and I dislike using Excel.

I needed a trivial back end for the scripts, and found that the old simple Python webserver has a version that can also run CGI scripts -- the command is
python -m CGIHTTPServer 8081
You can then create a cgi-bin/ folder, and files under that are eligible to be executed once appropriate permissions are set. One slight oddness is that path references are relative to (I think) where the python command is run, not the location of the script. I started coding in Python (a language I barely know, but I was just doing simple things) because at some point my sleep-deprived brain thought maybe I had to, but later a Perl script slotted in neatly as well. (I had some trouble because Angular fundamentally wants to POST in JSON formats, and Python fundamentally wants to read POST info as good ol' x-www-form-urlencoded, and while both can probably be persuaded to go the other way, at that point I was too tired to sort it out, and so I recycled an old jQuery/Perl pair I had previously written.) 

Anyway, looking for a bit of visual distinction, I threw in a large photo of a Rugby Scrum as a background, but of course then the risk was making things dificult to read. I set the various sections into background divs (inline-block'd so they were sized to hold their contents, not full browser width) but then I wanted to set the opacity, so they didn't block out the cool background. But I didn't actually want the controls to be opaque! What to do?

There seem to be some hacks to try and do it via pure CSS, but they didn't work for me. I realized I could set a repeating background PNG of a semi-opaque pixel. A suitable one can be found at the Wikiedia Commons. (The link is under "no higher resolution available"... I left clicked and then hit cmd-S to save the little bugger.)  My CSS was then 
.section {
    background-image: url("Translucent_50_percent_white.png");   
    display: inline-block;
    padding: 10px;
    border-radius: 10px;
}
I'm pleased with the result! I have only meager graphics design skills, so I like tricks like using an oversized photo, easy, underutilized hacks to make a page standout.

Thursday, July 17, 2014

angular options

Doing some angular 101 stuff for a hackathon at work.

Angular's ng-options parameter for a select is kind of obscure, and the official documentation is terribly arcane. This explanation, with examples, is about as good as anything I could find.

msg'ing about angular vs jquery

Pity my team's poor intern Patrick, having to listen to me pontificate about the old days of programming and grumble about some of the toolkits gaining in popularity... but maybe it was edumacational for him, a little...

[5:03 PM] Kirk : since i graduated in the mid-90s, I've always been a bit "full stack". but I've always run a few websites on my own, generally built "from scratch" (in Perl CGI), so I had great experience that some of my peers didn't in the front end, but also cheap backends to make it all work
  My blog http://kirk.is/ I've been running for 12+ years (it's morphed into something like a tumblr, but it started when "blog'" as a concept was kind of new and fresh)
  and http://loveblender.com/ -- that's been almost 20(!) in one form another, and is also a bunch of Perl CGI, with a big revamp around 10 years ago or so
  But I was weak on some of the newer front end stuff -- HTML5, and what CSS could do, and ESPECIALLY a cool tool called jQuery
  until I came to Pearson Education/Alleyoop.com, and they let me play a "UI Engineer" and I caught up
  I was there for 3 years, learned a ton
  jQuery is awesome, especially partnering with semi-advanced CSS/HTML5 -- doing animations and what not
  really changed my vision of what was feasible for me to do in the browser
  (for example, I semi-whipped up http://jpporchfest.org/ -- most of the coolest parts are Google Maps, but the whole page is a nice hack of some interactive stuff)
  ANYWAY
  So I get here, and a few months before I got here they voted and decided to go the angular.js route
  Angular is known to have a steep learning curve,
  it uses some arcane syntax
  and honestly, I'm not sold that the best way to be is "write your own tags".
[5:08 PM] Patrick : yeah, i pretty much just stared at it for about a full week until it clicked finally lol
[5:09 PM] Kirk : To me, it's a cool that I can look at html tags, and know they're html tags, not a big grab bag of custom attributes and new tag types
  I similarly wasn't font of JSTL in Java's JSP, which was a whole "build your own tags rather than sticking code bits in your HTML
  See, the thing is there are 2 languages: you have to know how to write tags, you have to know how to write code
  but there's a philosophy that says it's terrible to mix the two
  in JSP, that was ducking out into code snippets:
  <%= for(int i =0; i < rowCounts; i++){  %>
  and in Jquery, that's when you build HTML in your code
  jqueryELement.append("<td>"+Some stuff+"</td>");
  so I admit these are pretty ugly examples
  but they drive some engineers NUTS
  but I don't like their solution, which is : LETS ADD A *THIRD* LANGUAGE
  generally in the form of super-jacked-up tags
  me, I'm not very smart, so I prefer to do fancy thing with a limited number of simple tools than remember a new pile of smart tools
  so I just don't dig it very much
  it took me a while to put my finger on another philosophical difference with the "angular" (and similar libraries) crowed
  and that is this:
  coders tend to think more in verbs, or more in nouns
  the assumption that the latter is the best idea is why Object Oriented got so popular
[5:14 PM] Patrick : right
[5:14 PM] Kirk : but to me, it's the wrong point of emphasis
  "Programs, like People, should be judged by what they 'do' not by what you think they 'are'"
  So so many of these toolkts turn into "coding by configuration" -- you set up your objects to be the right thing, and then they DO the thing, and you're "saved" from writing that code
  but because you never have time to master the damn toolkits, you do it a little wrong
  and then god help you
  because that stack trace is likely to make VERY LITTLE SENSE
  it won't be a simple list of "I tried to do this, then this, then this", a nested stack trace like w/ Imperative Programming
  there's a big risk it's going to be a very tough to follow and debug set of abstract functions and what not
  I really think systems should be easier to model in your head.
  But I finally figured out why I dislike the Angular mindset:
  I mean in some ways, sure, the idea of the shared memory so controlling the DOM is powerful
  but the Angular coder thinks of the DOM and the code as one thing
  it's not a clean separation of (what to me is) the model vs the controller
  it's just a big tighty coupled stew, with the DOM trying to reflect the current memory state
  the programming I was more comfortable in, Bad Old jQuery, treats the DOM more like a billboard
  You write to it at certain times, you read from it at other times
  it stays pretty predictable in between those times, modulo animations and whatever the user is doing
  The DOM and my code are very loosely coupled, i.e. very carefully controlled and known access/info exhange points points
  Usually this type of loose coupling is considered a good thing :)
  but not here, in generl
  I haven't looked into it but I think Backbone.js might be more to my liking, providing certain tools you can take or leave, and while it imposes a certain set of assumptions on the data going back and forth from the server and what your REST URLs look like, it's value proposition is clear.
  Basically I evaluate every toolset on "does it have a good power/weight ratio", does the things it makes "easy" outweight the complexity of things you have to learn to use it well
  for me, so far, Angular fails that, rather hard.
  It does some cool stuff with modules, and testability, but not much that couldn't be done by a self-aware coder using simpler tools
[5:22 PM] Patrick : yeah, i can definitely see that
[5:23 PM] Kirk : One of the things that let me realize my philosophical "issue" with Angular, and anything that so tightly maps a bit of memory w/ the DOM, is thinking about animations
  man, I love making fun bouncy animations in JQuery
  and in angular, you can kind of do it, but it's awkward
  Thinking about why was instructional: it's because my style of jQuery is much more event driven. Something happens, my code tells the DOM to show something, and it's the most natural thing in the world to do it as a smooth transition rather than just "show this now"
  but angular, it's designed around quick, herky-jerky "change the screen so it looks like the memory! right now!"
  To me that's a boring life-- but I was spoiled learning HTML5/CSS/JQuery on a site for teens, where there was a stronger than usual excuse to make the page exciting and bouncy ("Juicy")
  Alright, thanks for listening
  I'm not saying I'm 100% right about everything
  and angular is a kick ass thing to have on a resume right now
[5:28 PM] Patrick : hahah yeah, there's that at the very least
[5:28 PM] Kirk : and I want to get more adept at it, get past its syntax weirdness (though man, supposedly angular 2 is not even going to try to be backwards compatible. which makes me SMH at the love for it)
[5:28 PM] Patrick : oh ugh that's not great
[5:29 PM] Kirk : I think the best tools do one or two small things well, and don't demand you structure your whole code base around it
[5:29 PM] Patrick : but yeah, i think it's good for me to kind of get a more expansive frame of reference
  after doing that with some functional languages in school and with JS here, it's really nice
[5:32 PM] Kirk : when I started jQuery / CSS for reals in 2010, the idea of making a simple image scroller (i.e. show an image with a next/prev arrow then scroll smoothly to the next one) seemed like black magic
  now that I know the CSS behind it, and the jQuery to power it, I could do it in my sleep
  (it's a good simple exercise in CSS, overflow:hidden , nested divs, positioning the innder DIV so that only the current imge part is sticking through the overflow:hidden frame wrapped around it all)
  A certain type of engineer hear really dislike UI, but for me, I love making things I can show off and also so easily peruse the guts of

Tuesday, July 15, 2014

a baby node server

A year and a half ago I made a node.js 101 post that turned out useful as I tried to make a little babyserver letting us here experiment with datatables outside of our heavy weight angular / Java server environment.

It looks like express.js, the library I used, has added a router(), so I decided to use that, and there's enough other new stuff to justify this blog post.

The upshot is: every request to /sites?count=###&offset=### will return an array of size "count". Each array entry is a map with key rownum (a row number starting at "offset") and rowNumber, which is the same information but with each digit turned into its word form. Any other request will attempt to serve content from the public/ folder under baby.js' working folder.

Here's the package.json:
{
  "name": "babyserver",
  "description": "a server for counting",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "4.x"
  }
}

After you have node installed, put that in an appropriately named folder, go to it, and run "npm install"

Here is baby.js:
var express = require('express');
var app = express();

var router = express.Router(); 
router.use(express.static(__dirname + '/public'));

//sites?offset=0&count=150

app.get('/sites',function(req, res) {
         res.type('application/json');
        var result = [];
        for(var i = 0; i < req.query['count']; i++){
            var d = i + parseInt(req.query['offset']);
            result.push({"rownum":d,"rowNumber":int2DigitWords(d)});
        }
res.send(result);
});

app.use('/',router);

app.listen(3000);
console.log('Listening on port 3000');

var digits = ['zero','one','two','three','four','five','six','seven','eight','nine'];

function int2DigitWords(num){
   var res = "", sep = "";
   var numString = num.toString();
   for(var i = 0; i < numString.length; i++){
      res += sep + digits[numString.substring(i,i+1)];
      sep = " ";
   } 
   return res;
}

Once that's in place, you can run "node baby.js" (or "nodemon baby.js") 
Then, I made a public/ folder and added this test.html that is a trivial jQuery table builder calling the main server:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>baby tester</title>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
function go(){
    $.ajax({
      url:
      "/sites?offset="+$("#offset").val()+"&count="+$("#count").val(),
      type: "get",
      dataType: "json",
      success: function(response) {
          populateTable(response)
      },
      error: function(e){
          alert("ERROR\n\n"+JSON.stringify(e,null," "));
      }
  });
}

function populateTable(res){
    var jqoTable = $("#mainTable");
    jqoTable.empty();
    for(var i = 0; i < res.length; i++){
        var row  = res[i];
        jqoTable.append("<tr><td>"+row.rownum+"</td><td>"+row.rowNumber+"</td></tr>");
    }
}

</script>
</head>
<body>
count:<input id="count" value="30"> offset:<input id="offset" value="10"><button onClick="go()">go</button>
<table border="1" id="mainTable"></table>
</body>
</html>

Monday, July 7, 2014

share link generator

http://www.sharelinkgenerator.com/ - just what it says on the tin, make links for FB and twitter, to prime people posting to their own wall/feed etc.

magnifying glass cursor

For some reason, the standard set of CSS cursors don't include a magnifying glass. But most browsers support .cur files, i.e. custom custor bitmaps.

Haven't tested it in IE yet, but one bit of CSS seems to be:

.page {
   cursor: url('magnify.cur'), -moz-zoom-in;
}

(There's some word that (older?) versions of IE needed it to be an absolute path, for some ridiculous reason.)

For magnify.cur, I found this public domain file, but I didn't quite like it because the lens part was opaque. So I found cursor.cc, an online .cur file editor, and made this magnify.cur. Lets call it public domain too.

Thursday, July 3, 2014

doodle.com for seeing when people are available

I was trying to remember the URL http://doodle.com/ - it's a convenient website for finding mutually agreeable dates for special events. (I had the same idea I was going to make for a friend, something called whenworks4u)