do internets

on internets doing computer

Rapid Prototyping with Haml/Sass + Compass, StaticMatic

Update: WOW - Large Posterous formatting leak, very dangerous...give us a minute to lock it down.

Update II: Fixed...kinda. Can't upload an image I wanted too at the moment. Later.

Well, I was going to write a post all about this - but Jerome already covered all the bases I was planning to. Allow me to quote his workflow:

My Prototyping Workflow >

1. Code one full page with no regards to modularizing the integration > any further than StaticMatic already does for you;

2. Once a full page is coded, modularize the code just enough so that > the next pages won’t require as much code. More on this in a future post;

3. Create another page;

4. Further modularize with the new elements in play. Using mixins and > helpers == modularization;

5. Repeat step 3 & 4 until everything is integrated;

6. Add in the javascript for more interactions in your prototype (it’s > worth it, big time); 

7. Deploy/commit your prototype.

http://jgn.heroku.com/2010/02/28/rapid-prototyping-with-haml-sass-and-ruby/

Exactly. Honestly - the time saved building things with this stack is unbelievable. You will be kicking yourself once you try this on just how much time you were wasting before. I was recently able to grind out the entire functional front-end for a web application, with styling and js interaction in about a 2 weeks. Seriously - jump over to Jerome's post and follow his advice to get started. You won't look back.

I'll just address a couple common objections quickly:

But Haml sux cause it depends on whitespace. Terrible to debug... 

That seems understandable - but in my experience, this has a lot more to do with the editor you are using. Haml throws very specific errors - e.g.

StaticMatic::TemplateError in /src/pages/program.haml

Indenting at the beginning of the document is illegal.

1: %h2
2: Create Performance Program

You know where it is - all you need is a good editor that properly illuminates indenting and spaces. I use and recommend SublimeText2 with a good Haml/Sass bundle.

Sub-coloring

Isn't adding Haml just another layer to interpret?

Sure, but you don't have to serve up Haml in production. What we are doing is interpreting the Haml/Sass when we push builds into the respective Html/Css.

It sucks writing content in Haml because of the indenting.

Yeah -> don't do that. Chris Eppstein has the definitive post on this. Haml is a tempting language. I strongly recommend using a filter like :markdown for content.

Got other question? Go ahead and shoot away. I'll try to answer whatever I can. Trust me - this will save you time as a front-end dev/designer.

I'm grateful for everyone who has worked on these meta-languages and frameworks. They make me love my work even more!

-Adc

Filed under  //   Design   compass   front-end   haml   javascript   prototype   rapid   ruby   sass   staticmatic  

Tip: Photoshop Layer organization for Table-like data

Pstables

Working with design elements in a table within Photoshop can often be a major bear. Your beautifully organized folders and layers can quickly spiral out of control into a headache inducing crap-load.  I have found it far more beneficial to arrange my elements and  layers in Photoshop by the columns of the table, rather than rows. This seems to make sense to me because - usually the objects in a column are of the same type. Also, because PS layers are arranged in a vertical manner - this seems to match columns. Often, you can even use one text block for the data of an entire column - and use the Line-spacing in the Text inspector panel to space each item into it's row.

It's not a perfect solution - but when someone proposes mass changes to a data-heavy Photoshop design* (see footnote) - it is far easier if your columns follow your Photoshop layers, rather than your rows.

======Bonus related tip=====

*Note: You may be asking - Wait! Why is there real data in your Photoshop file at all? Isn't this a mock up or something? Shouldn't it be placeholder stuff?

Yes, it is a mock up -> However, very often mocks are used in presentations to investors. Ideally, people (users) who view presentations could simply be told: "This is a mock-up: Don't be concerned about the content at the moment...," but in my experience, this NEVER works. Your presentation that is designed to show a mock layout is going along and suddenly, "Why does Dr. Brown only have X number of patients? That value doesn't make sense..."   ...and your whole presentation is railroaded by a question outside the scope and purpose of the mock-up. This is why people use dummy/placeholder data. However - dummy data often doesn't give an accurate portrayal of the info that needs a design, and furthermore, usually doesn't even achieve it's goal of avoiding distraction: "Why is that section in Greek? Our users are primarily English speaking.... Who is Lorem Ipsum?". Again, in my experience, it is far preferable to design around real values.

As a UI/UX person - this is a very frustrating trade-off - but you have to accept reality sometimes. Users (here - viewers of the presentation) have specific concerns about things. Thus, the easier you can make it on yourself to control and organize the data in your PS mock-up files - the better.

Filed under  //   data   mock-ups   organization   photoshop   tables  

Pathfinding, potions and feature creep

Well, not really feature creep as much as boredom with pathfinding code!

The full post is here:
http://codesquares.com/post/more_fun_with_pathfinding

User Stories, And then what?

UI/UX design is a broad field, and there are many important concepts that a good designer must learn along their career. I wanted to share a core principal that I have learned. 

Most everyone is familiar with 'User Stories.' e.g.

"User Mal wishes to log into application, see list of recent Alliance encounters by outcome."

Great, we have achieved an objective. This story might return:

Caught by Alliance cruiser, crew interrogated, cargo taken.

However, at this point, one of the most important questions is often left out:

And then what?

Very seldom do users complete a task - and then....unplug their computer. Users are always creating new "and then what" tasks in their minds, as they complete their current task. It is important to note here that as a UI/UX designer, it would be foolish to assume you can know or predict every possible "and then what" task that a particular user may generate. Still, it is critical to be asking the "and then what?" question and trying to come up with relevant answers. E.g.:

See list of successful capers?  
Plot revenge? 
Blame the Doc?
Browse cheap ship sensor upgrade deals on Amazon.com?
Purge all records of this event from system memory (Make sumpin' up)?

These are important questions to ask and are key to any user story. Even if you are only right a small percentage of the time, your users will thank you for trying.

Ok, so - now what?

Filed under  //   Design   UI   UX   theory   user stories  

A little Dweller prep-work

After looking at several roguelikes out there (Stone Soup, and now
Dredmor), we decided almost unilaterally that 20x20 was essentially a
stupid tile size and an increase was in order. At the same time - and
after playing quite a bit of Stone Soup and exploring large levels - I
decided that the game needs to have a scrolling camera to accomodate
arbitrarily-sized levels. The scrolling camera was borrowed from
Doglion's tutorial
(http://thedoglion.wordpress.com/2010/08/10/flashpunk-tutorial-03-camera-movem...,
so I won't go into it here. It was astonishingly easy to port.

Games seem to have a LOT of constants. Not only do you use them for a
bunch of general game settings, you also need a lot of thresholds
(min/maxes, bounds, edges, etc.), variances (how much you want your
thresholds or averages to vary). Then you have all of your arrays -
stats arrays, weapon arrays, layer arrays, direction arrays - and rather
than hardcoding them with text values which may or may not change on a
whim, and may not be consistent, it's best to use easily readable
constants as indices. I stole this from Dolgion most likely, but it's
something you should probably start doing right away, before you get
lost juggling arrays and indexes.

So, my original rendering code actually predates that particular
discovery, so resizing the tiles was a two-fold task. First, I had to
find all instances of "20" and change them to GC.GRIDSIZE, and then
change the GRIDSIZE to 32. This basically meant grepping for "20" and
then slogging through the code to make sure the 20s I was changing were
the right ones. If I had done this GC file from the start, all it
would've taken is a single line change in GC ...

Moral: if you find yourself using the same numeric or text value more
than 3 times, throw it into a constants file. If you don't have a
constants file, MAKE ONE NOW.

Quick easy tags + links

Since Express' Sinatra like routing lets me set up routes easily, I created a view where you could get all posts tagged with a certain tag. Then, in order to let the user get to them easily I fetched all the tags and de-objected them into a simple array. Not much to it, just a foreach inside a foreach; not the greatest of de-objectifiers but for a small set like tags should be it’s not really a big thing.

But then I had to display them and wasn’t sure how to, in jade. I know I can display “code” after a =, and use code after a – that will NOT display, but how do I merge code and text?

Turns out it’s even more JS friendly; you just use a + sign and quote your text just like you would do in a JS expression.

The second trick was that I needed both code in the HREF part of the tag, and some outside. That was pretty much straight out ruby syntax with tag parameters defined inside the () clause of the tag, and followed by another = after the tag. See below.

- for (var key in tags)
    .tag
        a(href='/tags/'+tags[key])= tags[key]

Nice!

All I have left for this to be navigable as I wish is pretty URLs for posts. I don’t expect an entry for that as it’s a pretty simple string-to-lower, replace non-alpha with null, replace spaces with underscores sort of thing – generate and save on data entry. Not exciting nor particularly interesting … nor – most importantly – nodey!

What’s next? Probably Dweller. :)

Fun with sequential execution

Codesquares is coming along nicely. I can now – thanks to Express – retrieve posts by URL or by tag. Thanks to MongoDB, implementing these things was a piece of cake as well; I just added columns for URL hash and tag array where I needed them.

Next, I wanted to get a list of tags to display in the sidebar. It took a while of figuring out whether the concept of NULL exists in Mongo (not really) or if I can check for ‘undefined’ (no), but I got the syntax eventually. Using a MongoDB fetch with params of

find({ tags: {$exists: true}})

lets me get only posts with tags. Next, adding filter params:

{ tags: 1, _id: 0 } ,

tells Mongo I only want the tags field, and to remove the always-included _id (you have to explicitly do this, even when specifying the fields to get) field. Tada, I now have an array of all tag arrays in the system. I have no idea if there is a potential future performance issue herem but for a blog I’m not overly concerned. You can always add a {limit: X} parameter if concerned.

So all is fine and dandy, but there is one problem: where do I put this query? Since node is asynchronous – meaning that you are not guaranteed results from a function before the next is executed – everything depends on callbacks to execute. So that means my initial query for posts calls back to the render function – but now I also want the tags to be loaded prior to render. What does that mean? That’s right cascading callbacks – while not overly complicated, they can be rather hard to read and parse later on. Just imagine you want 5 fetches to happen before page load.

function pageLoad(contents) {
  renderPage(contents)
}

function getPageContents(mode, TheUltimateCallback) {
  fetch(intoPosts, function() {
    fetch(intoTags, function() {
      fetch(intoComments, function() {
        fetch(intoXMLFeeds, function() {
          fetch(intoSideBarChatbox, function() {

// screw it, I lost count

TheUltimateCallback(withAllFiveFetchesContents); 
});

So it gets pretty gnarly, especially if someone else has to read this afterward. The above is a very simple case too, and I omitted all of the actual logic that goes on inside the callbacks – as you can imagine, it’s pretty nasty.

Step to the rescue!

Step has a couple of modes of operation. One is a straight method for sequencing functions when you need the output of one to feed into another. However, that doesn’t deal with callbacks so we use its second mode utilizing this.parallel(). I actually couldn’t parse the docs myself so all credit to The Wizard for this one:

Step(
function step1() {
    var callback1 = this.parallel();
    var callback2 = this.parallel();
    someAsyncThing1(function() {
        callback1(null, 123);
    });
    someAsyncThing2(function() {
        callback2(null, 456);
    });
},
function step2(err, result1, result2) {
    // result1 == 123
    // result2 == 456
}
})

In short, you assign a “GTFO of this function” callback to a variable, then run it with the parameters you wish to pass to step2. So I can run all five of my functions in parallel – since execution time doesn’t matter here – with five different callbacks, then collect everything in step 2. Step 2 waits for everything to finish, so you’re good as far as data availability.

Things get a little more hairy if you need the results of function 1 to go to 2, but function 3 can run in parallel – I probably won’t be tackling THAT one anytime soon, since my head already hurts. :P

Filed under  //   express   mongodb   node.js   step.js  

Layer Comps: Photoshop's strongest feature for UI/UX, Front-End Designers

Layercomps

In my opinion, Photoshop, while a great image editing application - is not particularly well tuned for web design. For instance, HTML and CSS are very logic and rule based, where-as photoshop has no intuitive way to set styling and rules. With that said, there is one outstanding feature that every web designer should be aware of: Layer Comps

Normally, if I can get away building wireframes and storyboards with HTML/CSS/JS, I will - but sometimes, a certain project will require a series of flat image mock-ups. Nothing really beats photoshop for this. However, with web design, there tend to be huge quantities of variations within one simple layout. Unlike print design, the web is interactive and has menus, hover states, alternate views, etc. Even if you are sticking to good layer organization practices, you will quickly find yourself over-run with layer groups. Showing or exporting a particular state can require hunting down dozens of layers, and toggling them on an off. 

Layer Comps allow you to save specific configurations (or states) of layers, including visibility, position, and even layer effects. This is very useful for setting up a single photoshop file, and saving various states of a UI interaction and display. And one of the best aspects of Layer Comps -> You can automate and export them all to image files with one action.

If you can make it past the epically dorky intro in the following clip, here is a decent overview:

Bonus tip: I have found it extremely helpful to further organize my photoshop documents, splitting them up based on their eventual web application Layouts and Views. For example: Index, Aggregate, ListView, SingleDimension, etc. Think of it this way: If your application controller will be setting a particular layout or view, use this as the Type and FileName of your PS document.

More ideas here: http://photoshopetiquette.com/

Filed under  //   UX   front-end   layer comps   organization   photoshop   tip   web design  

More node+mongo fun

Not feeling particularly inspired but wanting to do *something*, I set out to see how easy it would be to implement tags and view-by-post. After racking my brain for a while trying to figure out how to do post-by-url, I figured I needed another column (HAHA but not really, not in a doc-based db!) for a url-friendly header field. I'd figure out how to turn the header into these later; I was purely focused on getting the fetch part right.

While I was at it, I figured I'd need some tags. After briefly experimenting inside mongo's CLI I realized that the best way is to just add the tag hash into the existing posts hash. Off we go.

First, add a url-friendly url to a post. Since I'm just messing around I don't really care which one. Fortunately Mongo has a very unit-testing-friendly "findOne" function that will help us with just that.

x = db.posts.findOne();
x.hashURL = 'code-squares-now-with-mongo';
db.posts.save(x);

Done. Now, add some tags to the same post.

x.tags = ['mongo', 'node'];
db.posts.save(x); 

Done. By messing around with these, I found I can easily find posts by tag as mongo's find() searches within them. I didn't actually know that.

db.posts.find( {tags: "mongo"});

Done! Now to create the node handlers for each of these. We need one for tags with parameter and posts by parameter. Poking around in Express turned up the ability to parse params through regexp. Perfect!

    cs.app.get('/tags/:tag([0-9a-zA-Z]+)', function(req, res){
      cs.fetch('tag', req.params.tag, function(response) {
        res.render('index', {
          title: 'Code Squares by Tag',
          content: "Immature Technologies!",
          output: response
        });
      });
    });

So that will accept only alphanumeric tags and pass them in as req.params.tag. I then pass that to my own fetch function which determines whether to fetch by tag, post or just grab everything, and render the results in the index template with the provided results. At this point I'm really digging the whole concept of templates (with jade of course) and the Sinatra-like routing that Express provides.

I had a bit of fun with the lack of callbacks until I figured that particular thing out. I might save that for a day when I'm feeling braver about sharing the level of my event-driven noobishness. :P

 

Filed under  //   express   mongodb   nodejs  

Setting up a new node.js server with couchDB. But actually mongo.

I was all-set to go with couch. It actually installed on the Mac pretty well (for testing and general dicking around) and seemed like it was going to have a decent plugin for node. But then I suffered a series of crash and burns on Ubuntu as it consistently exited without an error message, failed to put the log file in a sensible place, failed to complain about permissions, and dumped out an incomprehensible erlang log of doom. Generally, couch on Ubuntu appears to behave like a dick (really it's the silent failures that infuriated me), so after 2-3 hours spent trying to fix it and making miniscule progress I gave up.

Enter mongo.

It didn't start very well, as this page tells you to "add a line to your apt sources". That's great guys, very specific and useful. Fortunately, the comment thread below was able to provide some help:

sudo add-apt-repository 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen'
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
sudo apt-get update
sudo apt-get install mongodb-10gen

And after running that (although I added the source location manually since I had to doublecheck something else in there anyway) everything went smoothly and mongo fired off its daemon immediately as well. We were off!

Well, sort of. Now came the tricky part of figuring out what to use for node. Running

npm find mongo

resulted in a pageful of results. As useful as NPM is, it won't tell you what's the best so it was off to the research lab (i.e. Google). I narrowed it down to 3 - native mongodb, mongoose (which seemed to streamline the native process and reduce some callbacks which as everyone knows are SO MUCH FUN in JS) and mongolia which seems to be vaporware. Down to 2. Mongoose has a great manual page which is ... utterly outdated with promises of updates to the manuals that are a year old. And the new version reintroduces all the complexity they seemed to try getting away from. Down to 1, native it is.

At the last moment I found something called Mongous which seemed to be a nice reduction of this absurdity (pseudocode):

mongo = new server;
db = new mongo db;
connection = new connection(db, mongo);
table = new collection(connection);
resultset = new query_on_table_through_connection_on_server;
do_stuff with results;
close query;
close table;
close connection;close db;

into this:

results = find_stuff_on_table(db);

Much better! However, after playing with it for a while and nearly losing my mind I have to conclude it's broken somehow. It only gave me results ONCE (!!!). I have no idea why. I might play with it some more, but for now native (ok, I exaggerated the setup a bit but the callbacks are pretty painful) seems to be the most reliable way to go. After having so much trouble with silent failures I'm all about the reliability.

Oh yes, don't forget to install nodejs-dev on Ubuntu; mongodb native plugin relies on node-waf to install itself, and that doesn't seem to be included just by installing nodejs itself. That was another 20 minutes of WTF-ness that could be avoided if more people posted their experiences. :)

Anyway, we seem to be go. I need to actually implement some styles on there (suggestions welcome :P) and then it'll be time to start hacking up some sort of UI for blog updates. I suppose authentication might not be a bad idea :P

Filed under  //   mongodb   node.js