Saturday, March 28, 2015

js quickie: random pastels

I found a page with some too clever by half random hex color generators but I know from experience that forcing things to be pastels leads to less of a "angry fruit salad" effect, so here's my modification of their code to constrain it to pastels:

function randomPastel(){
    return '#' + (function co(lor){   return (lor += ['a','b','c','d','e','f'][Math.floor(Math.random()*6)])&& (lor.length == 6) ?  lor : co(lor); })('');
}

tbh, it's probably not super efficient code (recursion hardly ever is!) and I'm even taken away some of the elegance by wrapping it in a boring-ly named function etc, but hey.

til: jquery $(document).ready shorthand

Oh, huh. Since I've know jQuery, I've used the formulation:

$(document).ready(function(){
  //do something
});

but in going over some jQuery UI example, I found out

$(function(){
  //do something
});

is a more concise replacement, that also waits for the DOM to be loaded.

Here's a pretty decent summary page including some other options.

Sunday, March 22, 2015

the joy of hack: diy "jsonp-ishness"

For a side project I've been working on, the library relies on a series of static JSON files to describe parts of the layout. Unfortunately, that part of the project wasn't working when put on the client's webserver. Investigating, I saw that my browser could successfully request the image files in the same folder, but the JSON was all 404'ing.

I asked for a screenshot of the folder listing, and the JSON files were present but listed as type "unknown". This was some kind of custom webserver, so I'm guessing it was configured to ignore filetypes it didn't know about --  including JSON, apparently.

The fix was straightforward-ish; hack the JSON loader for this set of files so it pulled value from a map hard-coded in the script itself. It was a sparsely populated map, only 4 or so of the 100+ pages had JSON that was anything but the empty array [], so the hack function returns an empty array if it couldn't find a value in the map, rather than me having to populate the map with 100 blank entries.

So for this arrangement, this technique was probably more efficient anyway. For that matter, this meant I could now pull up the project's index.html from the local filesystem and have it all work, which wasn't the case when the files were in external JSON.

So a win all around. Nothing too ground-breaking, just a kind of poor man's adhoc retelling of JSONP...

Friday, March 20, 2015

Thursday, March 19, 2015

qa joke!

"QA Engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a lizard. Orders -1 beers. Orders a sfdeljknesv."
--http://twitter.com/sempf

Wednesday, March 18, 2015

graph paper, free if you print at work

http://www.printfreegraphpaper.com/ Today I realized that if one has a need for a small amount of graph paper, and one has access to the Internet and a stocked printer, one no longer has a need for a small amount of graph paper.

Tuesday, March 17, 2015

handlebars 101

I really like the concept of handlebars (in terms of the library vs framework debate, and decoupling the "V" and "C" out of "MVC", unlike other heavier tools) but loops weren't as obvious. In older versions of Handlebars you had to write helpers, but like this stackoverflow describes now it's as easy as
{{#each myArray}}
    Index: {{@index}} Value = {{this}}
{{/each}}
and
{{#each myObject}}
    Key: {{@key}} Value = {{this}}
{{/each}}
and of course you can replace "myArray" or "myObject"with "." if you are passing in a simple array or object.

Also, if you want a comma-delimited list, that can look something like
{{#each myArray}}
    {{this}}{{#unless @last}}, {{/unless}}
{{/each}}
FOLLOWUP: if I call a post "handlebars 101" I owe it to my future self to have a reminder of the basic handlebars syntax in that post...
Keep in mind you can do "triple stash" if you don't want html escaped: {{{unescaped_html}}}

After including the handlebars js file, you make a template in a script tag like so:
<script id="hello-world-template" type="text/x-handlebars-template">
    <div>Hello, {{name}}</div>
</script>

You compile that template (probably keeping the resulting object around for reuse)

var helloWorldTemplate = Handlebars.compile($("#hello-world-template").html());

Then later you run that function, probably passing in a map of key/value pairs for substitution, and using (in jQuery) .html() or .append() to glom on the template result.

$("#someHolderObject").html(helloWorldTemplate({"name":"Kirk"}));


Monday, March 16, 2015

using data- attributes and jQuery-ing for them

One of the joys of writing small apps is that you can experiment with different paradigms of construction and finding DOM elements, messing with ideas for Model and DOM mapping.

I'm making a little status server pinger, using that trivial keyval store I made up (and the server proxy node stuff I found as well). One of the key requirements is that it be asynchronous; I don't want to hold up construction of the page on any given server query. In general, then, I'll have ajax queries returning en masse, and they need to put information in specific locations.

One technique would be to use arbitrary keys just for the Model/View mapping; either numeric indexes or just restrictions on key values (so they would make sense as element IDs). Or I could pass the DOM reference through the nested callbacks, so the function retrieving the data has the place on the page where it goes handy. Both seem kind of clunky... what I'd really like to do is be able to use arbitrary ids (for example, URLs which have 'illegal' DOM id characters) for elements on the page, and then find them via that id.

So jQuery is optimized for finding things by id and class, but you can also select elements by data attrbiutes. So if I had something like

<ul data-entriesForUrl="http://somesite.com"></ul>

I could find that element via 

$('*[data-entriesForUrl="http://somesite.com"]');
I'd guess that that's not efficient but should suit my purposes.

Saturday, March 14, 2015

facebook quick hit

One of those things I should have guessed I could have Googled for earlier... sometimes I get frustrated when I go to post a link to my just-updated site and the Facebook preview is out of date, the cache hasn't been updated. One hack solution might have been to add a meaningless "?foobar" to the end of the URL, so FB got it fresh, but that's problematic for several reasons. The correct solution is to go to the Facebook debugger page which presents options to do a new scrape, explains how to control the meta-info it grabs, and a few other things.

Thursday, March 12, 2015

quick hit: an endpoint with a slooooow server response

http://www.seanshadmand.com/2012/06/21/fake-response-server-slow-response-time-generator/ describes a cool little app, you can hit, e.g. http://fake-response.appspot.com/?sleep=5 and it will sleep 5 seconds and THEN return some JSON.

node quick hit: url pass through

So, the jQuery in your node based app can't reach out to other sites directly because of browser's same-origin policy.

Enter "request"

Assuming you're using express (After doing "npm install request --save"):

app.get('/url/:url', function(req,res){
  request.get(req.params.url).pipe(res)
});

and my jQuery was something like

$.get("/url/"+encodeURIComponent("http://somesite.com/etc/"),function(data){
console.log(data);
    });}

I guess it's not much worse than JSONP... anyway, this is just running in a trusted environment.



getput : trivial key/value pair persistence tool in node/express/fs_db and js

One thing I've confirmed while learning grails is that for many tasks I'm more comfortable doing the "heavy lifting" in the browser. The primary limitation is persistence; localstorage is fun, but not reliable for longterm things, and various users can't share information.

I thought a simple key/value store would be empowering for hackmatch-style products, so I wrote one in node.js, using the popular express library and fs_db, a trivial key/value store that writes to the filesystem. (Mostly this whole thing is a convenience wrapper for fs_db)

The package.json for that was
{
  "name": "getput",
  "version": "1.0.0",
  "description": "trivial persistent keyval GET and PUT",
  "main": "index.js",
  "dependencies": {
    "body-parser": "^1.12.0",
    "express": "4.x",
    "fs_db": "0.0.4"
  }
}

(So if you make a directory, put that package.json in it, and run npm install, it should handle all the dependencies)

I also made two subfolders: public/ (to store some static files to be served up by express) and db/ (for use by fs_db)

My main app was in index.js:
var DB = require( "fs_db" );
var express = require('express');
var bodyParser  = require('body-parser');
var app = express();
app.use(bodyParser.json()); 

// Create a new store, writing data beneath db/.
var store = new DB( "db" );

app.put('/db/:id', function(req, res){
  var id = req.params.id;
  var data = req.body.value;
  console.log(id);
  console.log(data);
  store.set( id,data );
  res.send();
});

app.get('/db/:id', function(req, res){
  var id = req.params.id; 
  store.get( id, function( error, value ) {
    res.send(value);
  })  
});


app.use(express.static(__dirname + '/public')); 
app.listen(3000);
console.log('Listening on port 3000');

Once that was in place, I created the js client, getput.js in public/:
function getput(pUrl){
    var url = pUrl;
    if(url.slice(-1) != '/') url += '/'; //ensure url ends with /
    return {
        get : function(key,callback){
            var newcallback = function(data){

                data=(data!="")?JSON.parse(data):null; //"" is unfound
                if(callback) callback(JSON.parse(data));
            }
            this.getraw(key,newcallback);
        },
        getraw : function(key,callback){
            $.get(url+encodeURIComponent(key), function(data){
                if(callback) callback(data);
            });
        },
        put : function(key,val,callback){
             this.putraw(key,JSON.stringify(val),callback);
        },
        putraw : function(key,val,callback){
            $.ajax({
                url: url+encodeURIComponent(key),
                data: JSON.stringify({"value":val}),
                type: 'PUT',
                contentType: 'application/json',
                success: function() {
                    if(callback) callback();
                }
            });
        }    
    }
}    
This has a dependency on JQuery, for the Ajax. (The one stumbling block I had in this was properly lining up the contentType and the correct express bodyParser (express recently changed how it handles body parsing, so many online examples are out of date) and I didn't feel like refrustrating myself by making it work with an Ajax wrapper replacement.)

4 functions are exposed, get()/put() (which assumes you're storing JSON) and getraw()/putraw() (which doesn't). You initialize it with the main url express is listening to. (Hmm- I probably should figure the correct way of having node take an argument from the commandline)

Also in public/ I put this simple tester index.html page:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>getput tester</title>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="getput.js"></script>
<script>
    var getrputr = getput("/db");
    function put(){
getrputr.putraw($('#key').val(),$('#val').val());
$('#key').val('');
$('#val').val('');
    }
    function get(){
getrputr.getraw($('#getkey').val(),function(data){
   $('#getval').text(data);
});
    }
</script>
</head>
<body>

<h1>put</h1>
key: <input id="key"> val: <input id="val">
<button onclick="put();">put</button>
<h1>get</h1>
key: <input id="getkey"> 
<button onclick="get();">get</button>
<span id="getval"></span>


</body>
</html>
It demonstrates getraw()/putraw().

I run the whole shebang with node or nodemon and bam!
clearly, this is why I wish to be a designer/developer hybrid

So a few gotchas still around, and stopping me from elevating this to a proper project until my free cycles return to a sane levels... the jQuery dependency, I should probably throw in a test or two, and then I think there might a value size limit for fs_db that I should document or code up.

Tuesday, March 10, 2015

php phun

So, some folks scoffed a bit at my praise of PHP but for small scale engineering I think it's decent. There are flaws: it's not really promoting a test-driven culture, it might not scale well, since it's basically doing the compile step all the time... still, I'm digging it.

One decision it undoubtedly got better than JavaScript: being a duck-typed language, and coming from a scripting culture, global variables are the norm. $foo here, $bar there, and (as reflect its Perl roots) variables tend to be initialized to sensible defaults, and things 'just work'. The clever bit is this: function variables DO default to local, and if you want to share in a global variable (in my case, for system-wide directory locations) you simply declare the variable "global", meaning you DO want the shared version. That seems far less error prone than JavaScript "forget that var, to put it in the local scope? Too bad, sucker! That's a global!"

There might be some subtleties of closures I'm glossing over, but in practice, it seems like a smart thing.

Monday, March 9, 2015

on the new macbook air

So most of the fuss in Apple Land today is about the watch, but I'm also intrigued by the new 12" Macbook Pro; I read this Gizmodo overview Apple Messed Up on the MacBook Air Again.

My vision with glasses is about 20/20 but personally I never ever notice the difference in screen resolution between my MacBook Air and my work Retina Macbook Pro. "1440 x 900 is a pitifully small resolution for modern times" seems like complete hyperbole to me, though I understand some people are more sensitive to the difference.

This new 12" thing is said to be very low-powered, and the compromises so wonky... this cartoon has never felt more true:



It's amazing what a completely adequate fulltime computer the other two Macbook Airs have proven to me for me (though disk space can be a bit tight); I guess I need to see what's going on with the keyboard and touchpad on the new model hands-on before I judge, but with the reduced processor and continuation of "thinness at any cost" aesthetic, I wonder if it is some kind of return to the netbook aesthetic...

...and that means with iPhone 6+ squeezing the iPad below, and then this kind of 'tweener system squeezing it from above... I could see the iPad line becoming the MacMini of Apple's portable technologies; there because it makes money, does some things well, and can easily piggyback on developments on its sibling systems. (I'll be enthused about a larger iPad Pro, especially if they started catering to artsy-types, swallowed their pride, and went for native support for a stylus. Swallowing their pride isn't Apple-like, but it has happened...)

And FWIW, I agree with the opinion that while it's not outside the realm of possibility but I'd be surprised if the Apple Watch becomes a gangbuster success.

Sunday, March 8, 2015

humble PHP

I'm building a sign up form for Jamaica Plain Porchfest. Technology wise, I decided to choose something that, if I ever parlay this into something other Porchfests might try to use, will be easy to deploy (even for less-techie volunteer groups) and I think PHP is the best bet in that regard. A decade ago Perl was my goto-language (so to speak) for this stuff, but PHP is feeling like right choice; a super gentle learning curve, without a real need for anything beyond the top of that curve. (When I first dabbled with PHP 13 or so years ago, there were parts that weren't ready for primetime, but now it feels reasonably mature and tends to have most needed functionality baked into its core.)

I'm making a semi-automated form builder using the file system and some baked-in JSON processing, and it's going well.

For the form builder, I found it most expedient to put some light html snippets in the code, a choice that seems to give other developers hives. But in grails and angular.js, the alternative is putting lots of logic and page flow control in the html... I don't see that flip as a tremendous improvement. The former gets a bit fiddly with quote marks, the latter gets extremely fiddly with whole new syntaxes to learn to bridge the gap. I only like to learn new concepts that empower me to do new things, not just marginally shinier ways to do the same old things...

(The only drawback is the dramatic unsexiness of PHP, resume-wise. For some reason I was heartened when a few days ago I noticed ".php" in some Facebook URL, though I know they're doing a lot of high powered server-side rendering, so it's more of an apples-to-jet-engines comparison.)
---
Thinking more about this: what are the limits to this style of development? In general, it's not great at setting up tests. But you know, the things that fail are exactly the things that unit tests (in particular) at bad at finding: system setup mistakes (which almost by definition aren't duplicated in the weird mocked-up, stubbed-out world of unit tests), and general flubs of syntax, which should never pass even the most basic developer tests.

So for that, it's probably suboptimal for really large complex engineering projects, but in my heart of heart I think those projects get set up on that scale more often than they should... so much of bespoke programming is very easy and can be kept simple, but there's a consistent Quixotic urge to try to build for the next decades, rather than keep it simple, and build stuff quickly that will last the next few years, and then will be easy to understand and replace when the time comes.

Anyway. Side note: another thing I admire in PHP is the default "lets blurp error messages to the screen". In the past I've been irked by that default, with the idea that things she be kept internal unless explicitly asked to blast to the screen, but for error conditions it's pretty great not having to dig up random logs and what not...plus it utilizes developer's egos, since any screw up will be right in front of the enduser. Failing loudly is critical in getting something up and running.

Saturday, March 7, 2015

nuh-uh, didn't say the magic word!

I decided to tear directly into the second Second "Science of Discworld" book when I realized it deals heavily with matters of mind and consciousness. It also talks about magic (here, in the Arthur C Clarke "indistinguishable from sufficiently advanced technology" sense) but ties in "magical" technology with the poor understanding of cause and effect we all tend to have as children:
Parents and carers are always transmuting the child's expressed desires into actions and objects, from food appearing on the table when the child is hungry to toys and other birthday and Christmas gifts. We surround these simple verbal requests with 'magical' ritual. We require the spell to begin with 'please', and its execution to be recognised by 'thank you'.
[...]
Coming home in the car and clicking the garage open, clicking the infrared remote to open or lock the car, changing TV channels - even switching on the light by the wall switch - are just that kind of magic. Unlike our Victorian forebears, we like to hide the machinery and pretend it's not there. So Clarke's dictum is not at all surprising. What it means is that this ape keeps trying, with incredible ingenuity, to get back into the nursery, when everything was done for it.
(Later they point out that you don't need high technology to continue this "making wishes" form of life, just lots of money -- "Feudal societies have a baronial class, who are in many respects allowed to remain in their nursery personas by being surrounded by servants and slaves and other parent-surrogates.")

I liked the reminder that the Victorians liked to expose the workings and fine engineering cleverness. But more than that, I was struck with how my preferences in software development are Victorian, in that sense. I prefer systems that "show their work" and expose the plumbing. That doesn't seem to be the dominant trend in the industry, however. In the late-90s, early-00s it was "Unix vs Microsoft" in development style, the latter giving you very powerful toolsets that a developer might not ever quite understand the flow of. Things "just worked" and coder life was productive and grand. Or they didn't, and coder life was misery and suffering. That Microsoft style seems to be seeping more and more into the stack that is still more at home on Unix-like systems, despite the culture those systems came from, the culture of relatively easy to understand and decoupled parts communicating, ideally via pipes.

There's a reductio ad absurdum of this, of course, that says why should I be uncomfortable with this kind of abstraction in technology when I accept so many others underneath it? I took some elementary assembly language in college, and even programmed an Atari game... but the amount of abstraction embedded in this laptop I'm writing this on is unfathomable. Just thinking about what's going on to get pixels glowing on the screen, the number of interlocked electronic subsystems in constant communication, a weird dance of impulse and intent... but, it's pretty reliable! It's acceptable to me because it hardly ever fails in subtle ways - or at all, for that matter. This is in contrast to these newer "framework of the months" for software development... if I'm coding with my preferred Imperative style of simple code, libraries for the tough stuff, stack traces that make sense... I know I can do pretty much anything a browser can allow. When using one of these magical frameworks, I have to see if the framework permits it, or if I'll be given the extra burden of working around it to meet the specification.

But, I persevere. Because these tools are powerful, and when I take enough time to really learn and get to know a toolkit, I'm empowered. Also, because my real goals are to do make interesting things, and a lot of the people with interesting things for me to make (and the budgets to pay me to make them) love these toolkits, and I want to be easy to work with.

Anyway.

The book extends some related ideas that to my ear starts leaning to Taoism:
A Spinozan view of child development sees the opposite of wish-fulfilment. There are rules, constraints, that limit what we can do. The child learns, as she grows, to modify her plans as she perceives more of the rules. Initially, she might attempt to cross the room assuming that the chair is not an obstacle; when it doesn't move out of her way, she will feel frustration , a 'passion'. And throws a paddy. Later, as she constructs her path to avoid the chair, more of her plans will peaceably, and successfully, come to fruition. As she grows and learns more of the rules - God's Will or the warp and woof of universal causation - this progressive success will produce a calm acceptance of constraints: peace rather than passion.
(I had to confirm I knew what "throwing a paddy" meant from context... and like I feared, it's a bit racist.)

I hadn't heard as much about Spinoza in a while, I think I dig that kind of pantheistic outlook.

Magic!

Wednesday, March 4, 2015

i'm not a designer but i play one for charity

This is a very rough first draft (and a bit insufficiently diverse) but I like the general layout I and design I came up with: