I’ve been busy!

Me pointing at our Smartwalk feature for TransitScreen in Minneapolis.

Hey fam, I’ve been rather busy at TransitScreen lately. Sorry this blog has been rather neglected. Since the last post, I’ve had to become an Angular 1 ninja overnight and a Karma unit testing fiend. In addition it’s rather amazing what you get out of user testing!

I hope to get back and share some of my thoughts on asynchronous land and user interface design.

Have a wonderful Holidays!

Sending Angular $http POST Data to PHP

In the case of sending form data in Angular, $http POST data information is serialized as “application/json” which is not interpretable by PHP.

You have to transform the request (the form data object) into a format that it understands. The easiest way is to configure the $httpProvider.

/* Because PHP sucks */
myApp.config(['$httpProvider', '$httpParamSerializerProvider', function($http, $httpParamSerializerProvider) {
    var paramSerializer = $httpParamSerializerProvider.$get();
    $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
    $http.defaults.transformRequest = function(data) {
        return paramSerializer(data);
    };
}]);

 

TransitScreen Redesign Featured On City Lab

So delighted to see TransitScreen was featured on CityLab!  Our redesign was a year long effort between Isometric Studio in New York and our management team.  As UI Designer, I had to lead the implementation process after delivery and return to them for refinements.

https://www.citylab.com/transportation/2016/12/a-smarter-way-to-visualize-zillions-of-travel-options/511322/

Code Examples: CSS Squares

Back in the 2000s, creative agency websites really liked the grid effect where you would hover over a block in a grid and that block would expand into some content.  Of course then, people would use Flash or some complicated jQuery contraption.  I created my own code example of this for a client once to demonstrate a CSS3 based design working with typical HTML element flow instead of overriding everything with position absolute and calculating block sizes on the fly.   This example also serves to teach how powerful CSS inheritance can be to create series of movements that look like fancy Javascript.

It’s not a perfect example because if a user mouseovers too quickly to the next block, the widths may exceed the row and break to the next line.  A solution could be to give some extra spatial buffer to the .main-content wrapper.   jQuery is still used here to trigger the next child block to be “hidden.” Since the transitions are set the same, one smoothly replaces the other.   At the end of the row, it triggers the previous child.

 

 

How to Quickly Backup and Restore MAMP’s phpMyAdmin Databases

It took me some Googling to nail down the question “Where does MAMP’s phpMyAdmin (PMA) store mysql databases in OSX?” so I thought I’d summarize my findings.  The reason mysqldump isn’t as convenient is that MAMP is purposely GUI-focused, so switching brains and trying to navigate Terminal to MAMP’s mysql core is annoying and not intuitive (MAMP stores things all over the place).  Also mysqldump doesn’t easily like dumping all databases.  If we’re GUI, then let’s see if there’s a GUI solution and voila there is.

  • MAMP’s PMA stores its database files (.frm) inside HD/Library/Application Support/appsolute/MAMP PRO/db/mysql
  • Simply navigate to that folder and zip up the entire mysql folder (be wary there is also a separately named mysql folder inside this folder, ugh).
  • Throw that onto your Desktop or backup drive.
  • Let’s say you return to a fresh install of MAMP PRO, navigate back to that folder and copy all the files including ibdata1, ib_logfile1, ib_logfile0 which contains all the permissions and sql structure for phpMyAdmin.
  • Restart MAMP (which restarts mysql) and PMA should be refreshed with all your databases like nothing ever happened.

Similarly now you know how to cherry pick from old Time Machine backups instead of needing to setup the MAMP environment all over again.   Of course different versions of PMA may have changed that db folder structure, so be wary of that.

Google Maps Marker Toggle Code Example

markertoggle
As a followup to my strangely popular KML Toggle example on Google Maps, someone has prompted me to do a Marker Toggle code example.  I’m pretty late to the game to notice that Google updated some of the Maps library syntax, you can now for example pass an object literal for latitude longitude.  As a warning, the code is a bit clumped together to briefly give an example into working with markers.  I wouldn’t recommend master functions that do everything under the sun which is why Angular is a great library to separate your concerns and dependencies.

This example organizes code as follows:

  • Marker information is formatted as a json object, the standard format used today for data sharing.
  • A single global map variable.
  • The Google Map initializeMap() procedural function
    • In addition this function creates markers and your DOM controls.
  • The createMarkers() function that instantiates markers with infowindows and stores it back in the json.
  • createControls() dynamically generates the controls based on information in the json. This would be akin to using Angular’s ng-repeat.
  • toggleControl() is a state changing function that sets your checkbox state, class style, and marker visibility. It uses inverted logic, if the checkbox is checked, then do the opposite.

Click here to the Google Maps Marker Toggle code example.

// Our data source object in json format 
var markerJson = {
    "coffee1": {
        "name": "Urban Bean Coffee",
        "coordinates": {
            "lat": 44.958813,
            "lng": -93.287918
        }
    },
    "coffee2": {
        "name": "Spyhouse Coffee",
        "coordinates": {
            "lat": 44.998846,
            "lng": -93.246241
        }
    },
    "coffee3": {
        "name": "Blue Moon",
        "coordinates": {
            "lat": 44.948480,
            "lng": -93.216707
        }
    }
};

// Set a global variable for map
var map;

// Setup a listener to load the map via Google
google.maps.event.addDomListener(window, 'load', initializeMap);

/* Google Maps Related Functions */

// Initialize our goo
function initializeMap() {
    var options = {
        center: {
            lat: 44.9812,
            lng: -93.2687
        },
        zoom: 13,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    map = new google.maps.Map(document.getElementById("map_canvas"), options);

    // Create markers into DOM
    createMarkers(markerJson);

    // Create controls dynamically after parsing json
    createControls(markerJson);
};

// Instantiate markers in the background and pass it back to the json object
function createMarkers(markerJson) {
    for (var id in markerJson) {
        var shop = markerJson[id];
        var marker = new google.maps.Marker({
            map: map,
            position: shop.coordinates,
            title: shop.name,
            animation: google.maps.Animation.DROP
        });

        // This attaches unique infowindows to each marker
        // You could otherwise do a global infowindow var and have it overwrite itself
        marker.infowindow = new google.maps.InfoWindow({
            content: "This coffeeshop is called " + shop.name
        });

        marker.addListener('click', function() {
            this.infowindow.open(map, this);
        });

        shop.marker = marker;

    }
};

// In this example create the controls dynamically with all checked, obj is each "coffee" listing
function createControls(markerJson) {
    var html = "";
    for (var id in markerJson) {
        var shop = markerJson[id];
        html += '<li><a class="selected" href="#" id="' + id + '" onclick="toggleControl(this); return false"><input onclick="inputClick(this)" type="checkbox" checked id="' + id + '" />' + shop.name + '</a></li>';
    }
    document.getElementById("controls").innerHTML = html;
};

// Toggle class, checkbox state, and marker visibility
function toggleControl(control) {
    var checkbox = control.getElementsByTagName("input")[0];
    var shop = markerJson[control.id];
    if (checkbox.checked == true) { 
        checkbox.checked = false;
        control.className = "normal";
        shop.marker.setVisible(false); // If you have hundreds of markers use setMap(map)
    } else { 
        checkbox.checked = true;
        control.className = "selected";
        shop.marker.setVisible(true); // Similarly use setMap(null)
    }
}; 

// Cleanup function, resets controls, hides all markers, does not destroy
function removeAll() {
    for (var id in markerJson) {
        var shop = markerJson[id];
        shop.marker.setVisible(false);
        document.getElementById(id).className = "normal";
        document.getElementById(id).getElementsByTagName("input")[0].checked = false;
    }
};

// In this case we are keeping the input box for accessibility purposes, so we bubble up the click event to the parent control
function inputClick(input) {
    input.parentElement.click();
};

jQuery Handling of CSS Classes

Though CSS3 transition animation support is still a little wonky, it’s getting better every day.  I’ve decided to pass all animation handling to CSS versus previously using jQuery’s fade functions.   jQuery is now simply the trigger, adding and removing classes.

Example: Fading Modal Box

A “modal window” is the technical term given to those annoying pop-ups in Windows.  It’s synonymous with dialog or alert.   In websites, the same concept is typically used to pop-up a larger version of a smaller image, as in a blog post.  For me, they’re useful as “page” content displays for websites which need to remain static, like in use of maps or dashboards.

jQuery

In the example below, a click listener handles the entire operation:

  • .modal-toggle is assigned to the button calling the action. ie: <a href=”#about” class=”.modal-toggle”>Click for About</a>
  • Of course, prevent default link action.
  • variable target references the href URL of the button or link. #about
  • This URL points to a div ID acting as my .modal. ie: <div id=”about”></div>
  • Next I add my “master” css class called .transitional to the .modal div.  I use a master class for applying CSS transition animations because obviously I don’t want to be adding this CSS to every single class that needs it — which increases browser load.
  • Now I’m using the link itself to judge if we’ve clicked on this before.
    • If the link has class active, then do the opposite first.  I don’t like testing negatives for if/else.
      • Remove class active, and remove class active on the modal.  Note we have to queue a delay to hide() a.k.a display: none because otherwise it won’t wait for the transition to finish. I set it to 500 ms ahead of my 400 ms.  See that hide() has a numeral hide(0) because this notifies jQuery to queue that operation; you could conceivably add more queued operations 1, 2, 3, etc.  This is required or delay does nothing.
    • If the link does not have it, let’s do our magic.
      • Add class active, then on the modal add class active.   Note we have to queue a delay on the addClass because otherwise the div will show() a.k.a. display: block immediately without waiting for the addClass.  The fancier queue function is used here because addClass cannot be queued itself.  So we have to nest it inside the available jQuery queue function.  dequeue() is required to again notify jQuery that addClass is a queued operation.   The delay is shorter, I’m just giving the browser time to separate the actions between show() and the addClass.
      • The animation is triggered by addClass(“active”) for the .modal div.
$(".modal-toggle").on("click", function(e) { 
        e.preventDefault();
	var target = $(this).attr("href");
	$(target).addClass("transitional");
	if ($(this).hasClass("active")) { 
		$(this).removeClass("active");
		$(target).removeClass("active").delay(500).hide(0);
	} else { 
		$(this).addClass("active");
		$(target).show().delay(10).queue(function(){
		    $(this).addClass("active").dequeue();
		});
	}
});

CSS

Simple enough!  The CSS is organized as follows:

  •  .modal creates our main control “layer”.  I’ve offset it from the top, assuming that’s where our main navigation link for .modal-toggle exists.  We don’t want to cover that up or we can’t close it.
  • .modal.active triggers our CSS animation to fade opacity to 100%.  That’s all it needs.
  • .content is an additional div layer nested under .modal because in general you should separate information out.  Also this lets you style the actual visible window as if it was centered on the page.
  • .transitional is my master CSS class.
.modal { 
	position: fixed;
	top: 5%;
	left: 0px;
	z-index: 1000;
	display: none;
	opacity: 0;
	width: 100%;
	height: 95%;
	}

.modal.active { 
	opacity: 1;
	}

.modal .content {
	position: relative;
	z-index: 200; 
	width: 80%; 
	height: 80%;
	margin: 0 auto 0 auto;
	background: #fff;
	padding: 20px;
	}

.transitional { 
    -webkit-transition: all 400ms ease-in;
    -moz-transition: all 400ms ease-in;
    -ms-transition: all 400ms ease-in;
    -o-transition: all 400ms ease-in;
    transition: all 400ms ease-in;
}

Get template name in WordPress

Generating the template name isn’t really a big deal, globally it’s available via echo get_option('current_page_template'). But in this case, when I was generating a slideshow of multiple pages, I needed to pass the slideshow query to it. So I had to write up my own for functions.php.


function get_template_name($query1) { 
	$template_name = get_post_meta( $query1->post->ID, '_wp_page_template', true ); 
	$length = strlen($template_name) - 4;
	if (strpos($template_name, '.php')) { 
		$template_name = substr($template_name, 0, $length);
		return $template_name;
	} else { 
		return $template_name;
	}
};

Call it after the while condition and it will generate the template name for each post (ie: echo get_template_name($query1)) The template name is stored like a simple meta value and includes the .php extension. So this will check for that to strip it out, otherwise will return ‘default.’

Why is this necessary for my slideshow? Well, some pages are to be laid out differently, this allows the CSS to make multiple slides of differing layouts.

Toggle Map Style and the Polygons Shown

In my previous Google Maps examples, I store all objects such as polygons and markers in an overlayArray.  Having a “global” theme change that doesn’t just alter the mapStyle, but also polygons is as simple as looping through your Array and setting options.   Here I’m using variable t1 to control the true/false variable, on a live site you should probably do something local such as adding a Class name to the button.

 

  var t1 = true;
    $("#toggle-theme").click(function(e) {
        e.preventDefault();
        if (t1) {
            t1 = false;
            map.setOptions({
                styles: mapstyleDefault
            });
            for (var i in overlayArray) {
                overlayArray[i].setOptions({
                    strokeColor: '#ff0000',
                    fillColor: '#ff0000',
                })
            }
        } else {
            t1 = true;
            map.setOptions({
                styles: mapstyleAlternate
            });
            for (var i in overlayArray) {
                overlayArray[i].setOptions({
                    strokeColor: '#29800b',
                    fillColor: '#29800b',
                })
            }
        }
    
    });

Remove Overlays

I find the most elegant way to deal with Google Maps objects from markers to polygons is to push them to a global array.  The simplest popular method is merely to use this array for clearing all objects.  The example below does that and references a separate InfoWindow array.  Simply setMap null, close the windows, and if needed reset all the arrays to 0.

function clearOverlays() {
    for (var i in overlayArray ) {
      overlayArray[i].setMap(null);
    }
    for (var i in infowinArray ) {
        infowinArray[i].close();
    }
    overlayArray.length = 0;
    infowinArray.length = 0;
};

Though this will suffice for simple loop operations where you basically call back and forth a few items, I found that for more complex objects and maps, a fancier robust function is needed to manage. In my case, I am storing a “complex” polyline, that is many polyline path segments which must be individually rendered.  For example if your path loops around a city, it’s clear you won’t be able to accomplish rendering that in one path.  KML notation already recognizes this and so groups many LineSegments into a MultiGeometry structure.  Manipulation of a KML layer’s stroke, color, etc is easy.  Unfortunately Google Maps does not have a multigeo, and using a Polygon object will not suffice as it automatically draws in the end points.  As well, your polylines may not necessarily connect but are associated with each other.

Here is my revised kitchen sink clear overlay function that offers a target and exclusion option.

  • clearOverlays(“all”) will simply result in everything being removed.
  • clearOverlays(20) or clearOverlays([20, 22, 25]) results in clearing only the targeted numbers being removed.
  • clearOverlays(“all”, 20) or clearOverlays(“all”, [20, 22, 25]) results in everything except the number or array being targeted.
  • Note you can’t do both such as clearOverlays(22, [80]), it will simply ignore the exclusion and go with the targeted item.  Of course this is also illogical.
  • The function takes into account, as in my case, whether you have an array within an array (“embedded”) as is required for grouping polylines or markers.
function clearOverlays(target, exclusion) { 

    // this function to go a level down into the array of objects (polylines, etc)
    function removeObj(a) { 
        if (typeof a[i].setMap == "function") { 
            for (var i in a) { 
                a[i].setMap(null);
            }
        }
    }

    if (target !== "all") { // just targeting something for removal

        if (typeof target == "number" || typeof target == "string") { 
            for (var i in overlayArray) { 
                if (overlayArray[i][0] == target) { removeObj(overlayArray[i][1]); }
            }
        } else { // if array

            for (var i in overlayArray) { 
                if (inArray(overlayArray[i][0], target)) { 

                    if (typeof overlayArray[i][1].setMap == "function") { 
                        overlayArray[i][1].setMap(null); 
                    } else { 
                        removeObj(overlayArray[i][1]);
                        }
                };
            };

        }

    } else { 

        if (exclusion == "") {  // target all, remove everything
            for (var i in overlayArray) { 
                if (typeof overlayArray[i][1].setMap == "function") { 
                    overlayArray[i][1].setMap(null); 
                    } 
                removeObj(overlayArray[i][1]);
                }
            } else { // target all but exclusions
            for (var i in overlayArray) { 
                if (inArray(overlayArray[i][0], exclusion)) { //ignore 
                } else {
                    removeObj(overlayArray[i][1]);
                    }
                }
            }
    };    

    function inArray(needle, haystack) { // needle being a string
        for (var i = 0; i < haystack.length; i++) {
            if (haystack[i] == needle) return true;
        }
        return false;
    }
};

 

Google Maps KML Toggle

My new KML toggle method is as follows which more logically lays out the variables and functions involved. The true improvement is that in order to add new KML files to the map, you simply add a new row to array kml. The code generates the rest. This code is literal easily adaptable to more asynchronous applications.

Code below or view it on Github.

<html>
<head>
<title>KML Toggle Example</title>

 <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>

 <script type="text/javascript">

    // define some variables to be used later
    var map;
    var overlays = [];
    var kml = {
        a: {
            name: "MPLS/STPL",
            url: "https://maps.google.com/maps/ms?authuser=0&vps=5&ie=UTF8&msa=0&output=kml&msid=212971981154994583939.0004b06640255267e038c"
        },
        b: {
            name: "Bicycling Tour Routes",
            url: "https://maps.google.com/maps/ms?authuser=0&vps=4&ie=UTF8&msa=0&output=kml&msid=212971981154994583939.0004902a1824bbc8c0fe9"
        }, 
    // keep adding more, the url can be any kml file
    };

    // initialize our goo
    function initializeMap() {
        var options = {
            center: new google.maps.LatLng(44.9812, -93.2687),
            zoom: 13,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        }
        map = new google.maps.Map(document.getElementById("map_canvas"), options);

        createTogglers(); // in this example I dynamically create togglers, you can otherwise use jQuery
    };

    google.maps.event.addDomListener(window, 'load', initializeMap);

    // this does all the toggling work, id references the a b names I gave the kml array items

    function toggleKML(checked, id) {

        if (checked) {

            var layer = new google.maps.KmlLayer(kml[id].url, {
                preserveViewport: true,
                suppressInfoWindows: true 
            });

            kml[id].obj = layer; // turns the layer into an object for reference later
            kml[id].obj.setMap(map); // alternative to simply layer.setMap(map)
        }
        else {
            kml[id].obj.setMap(null);
            delete kml[id].obj;
        }

    };

    // in this example create the controls dynamically, prop is the id name 
    function createTogglers() {

        var html = "<form><ul>";
        for (var prop in kml) {
            html += "<li id=\"selector-" + prop + "\"><input type='checkbox' id='" + prop + "'" +
            " onclick='highlight(this, \"selector-" + prop + "\"); toggleKML(this.checked, this.id)' \/>" +
            kml[prop].name + "<\/li>";
        }
        html += "<li class='control'><a href='#' onclick='removeAll();return false;'>" +
        "Remove all layers<\/a><\/li>" + 
        "<\/ul><\/form>";

        document.getElementById("toggle_box").innerHTML = html;
    };

    // easy way to remove all objects, cycle through the kml array and delete items that exist
    function removeAll() {
        for (var prop in kml) {
            if (kml[prop].obj) {
                document.getElementById("selector-" + prop).className = 'normal'; // in normal js, this replaces any existing classname
                   document.getElementById(prop).checked = false;
                kml[prop].obj.setMap(null);
                delete kml[prop].obj;
            }
        }
    };

    // append class on select, again old school way 
    function highlight(box, listitem) {
        var selected = 'selected';
        var unselected = 'normal';
        document.getElementById(listitem).className = (box.checked ? selected : unselected);
    };

 </script>

<style type="text/css">
#toggle_box { position: absolute; top: 100px; right: 30px; padding: 10px; background: #fff; z-index: 5; box-shadow: 0 5px 10px #777 }
ul { margin: 0; padding: 0; font: 100 1em/1em Helvetica; }
ul li { display: block; padding: 10px; margin: 2px 0 0 0; transition: all 100ms ease-in-out 600ms; }
ul li a:link { border: 1px solid #ccc; border-radius: 4px; box-shadow: inset 0 5px 20px #ddd; padding: 10px; font-size: 0.8em; display: block; text-align: center; }
.selected { font-weight: bold; background: #ddd; }
</style>

</head>
<body>
<div id="map_canvas" style="width: 100%; height: 600px;"></div>
<div id="toggle_box"></div>
</body>
</html>

Convert KML to PolyLine

To convert a KML file to a native Google Maps rendered polyline is essentially the process of parsing the KML, which is XML syntax, into its constituent parts, that being coordinates within a object.

I found the conversion necessary in the process of pulling stored KML data from a Google Fusion Table. If the KML data is stored as Location type, then it will return a MVCArray which can easily be picked apart with for loops to extract the coordinates. However, I have discovered that Fusion Tables has some issues or limitations with very complex KML objects that are not yielding all coordinate arrays, resulting in a half-rendered line. As such I’ve “manually” parsed the KML as a string. The two methods are presented.

success: function(data) {

var rows = data['rows'][0];

for (var i in rows) { 

var geo = rows[i]['geometries'];

	for (var j in geo) { 
	var linesegment = geo[j]['coordinates'];
	drawLine(linesegment);
	};

}


function drawLine(linesegment) { 
	var coordArray = [];
	console.log("rows");
	for (var i in linesegment) {
		var lat = linesegment[i][1];
		var lng = linesegment[i][0];
		var lineCoord = new google.maps.LatLng(lat, lng);
		coordArray.push(lineCoord);
	}

	var randomnumber = Math.floor(Math.random()*7);

	var colors = ["#FF0000", "#00ffff", "#FF00ff", "#Ffff00", "#555555", "#222222"];

  var routeLine = new google.maps.Polyline({
    path: coordArray,
    strokeColor: colors[randomnumber],
    strokeOpacity: 1.0,
    strokeWeight: 4,
  });

  routeLine.setMap(map);
  
}

Header Image via Featured Thumbnail

A lot of sites employ a header splash, notably photographer websites.  It is a highly requested feature of clients.  Fortunately WordPress has an easy hook with its featured image (thumbnail) setting that will allow an admin to set whatever image they wish for each post or page.  First, in functions.php, activate thumbnail support.

add_theme_support( ‘post-thumbnails’ );

Then in your theme file, such as header.php, call it forth.

<?php if (has_post_thumbnail( $post->ID ) ) : // is thumbnail set?
$image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), ‘single-post-thumbnail’ ); // grab image attr array ?>
<header class=”main-header” style=”background-image: url(‘<?php echo $image[0]; // the first array item is the src ?>’)”>
<?php else : ?>
<header class=”main-header” style=”background-image: url(‘<?php bloginfo(‘template_url’); // define a default in your theme folder ?>/images/defaultbg.jpg’)”>
<?php endif; ?>

Then CSS3’s background-size will do you well.   Alternatively you could have it echo into an img tag and set width, height 100% auto.

 

Thought Process of Working in Google Maps

Sometimes as a front-end you think by taking the “back-end” methodology route, you can accomplish great feats. In the end, the answer is often much simpler than you think. Such as in this example.

I need to find the coordinates of the center of a polygon.

Easy right?

First problem, the polygon is stored in KML format in a Fusion Table. Let’s use my awesome getJSON call from last year to retrieve the data, oh wait, the API has changed, okay let’s go to their ajax example even though it’s technically equivalent. Now the data is an object, oh I can’t work with an object.

Google, google, google…

Let’s try Google visualization since they enjoy offering different ways to find the same carrot. Oh okay I have to load Goog JS. More resources, the better! A dozen for loop iterations later, I still have an object.

Okay let’s try stringifying by manually pulling out the coordinate information from the KML object with js splits, parseFloats and jQ text() conversions. Great now I have 20 lines of coordinate data because it’s a complex polygon.

Except to retrieve the bounds of the polygon, I need a RECTANGLE. Argh! Perhaps if I become a zen master of algorithms, I can determine which four lines of coordinates are the approximate four corners of an averaged rectangle. Easy!

Google, google, google…

Try getCenter, getBounds and anything that gets something out of nothing. Thinking I need to extract the raw KML formatted data as is and then use to to call forth KmlLayer inline. Half an hour later, I realize I’m trying to thrust a packet of data into what is only a URL call.

Maybe I should extract the first coordinate point of each polygon via strlens and use that as an approximated marker location with some math adjustments. Oh wait, every polygon’s first coordinate point is all over the place. Banish the thought.

Google, google, google…

Answering some random questions on StackOverflow that do not relate but came up anyway.

Upon consulting every inch of Google Maps V3 developer guide, I come to realize I just need to zero in on the infoWindow’s self-centered latLng itself.

Several hours and dozens of lines of test code later, I actually needed just one line of code.

Yes sir, you can have labels in the middle of each polygon now.

/die.

Does Lean UX Replace Style Guides

Two years ago I read a great article by Smashing Magazine on “Style Guidelines for Brands and Websites” which suggests designers offer style guides to clients post-project. Often in the rush to the deadline, we forget that a website is never completely done and will continue to live on, organically changing and adapting itself. Having a style guide certainly gives the client evidence that actual strategic thought went into development of their brand. At the University of Minnesota, I became very familiar with their style guides during HTML 4.01’s reign. From a systematic organizational perspective, style guides were a doctrine that constrained specific uses but also allowed room for creativity in the spirit of the guide.

When I think about traditional style guides in the context of Lean UX, in reducing waste from iterative processes, I realize they are paradoxically outmoded and transgressed. Style guides can take many forms and for web often manifest in layout standards (wireframes) and graphic standards (color, shape, size, position). In essence a web style guide creates a prototype’s framework for you, and it’s up to you to fill in the pieces. In an ever evolving start-up environment, the visual standards are constantly changing, being thrown away or restructured into new forms. Why bother creating a guide when you know tomorrow even the very fundamental aspects of your product will change.

Now, at the same time, a style guide can act as a fundamental bedrock because it infuses the overall process with a sense of purpose and unity. Style guides come from the print environment where seemingly minor factors like line-height and line thickness can make or break. As we know from conceptual design or product design in general, that form is sometimes eminently more important than function (assuming the function is worthy). Twitter and Facebook are essentially communication mediums but their forms, in 140 characters or in dynamic multi-level posts, change the user experience. Mac OS X is a system that clearly has a style guide, that very specifically dictates every visual graphic to the point where outside developers and their designers must follow the edict. Ironically it is Windows that has shown a penchant for anything goes, and we know how that’s turned out.

Style guides are different from documentation. Jeff Gothelf writes in “Lean UX Is Not Anti-deliverable” (5/23/2012):

The focus should still be to design the best experience while minimizing the amount of time designing the wrong ones — not to design documentation that describes these design hypotheses.

Lean UX is about a specific design solution as a scientific question. Does my new app interface do what it intends without any instruction? The documentation outlining wireframes and hierarchy are what needs to go. On the other hand I see style guides as addressing a higher level question, whether the design communicates not just purpose but cohesion with the message, brand and experience. If anything, style guides answer questions of the strategic plan. The new Digg is perhaps the best example of a redesign that, one can argue, does exactly the same thing, but in form answers such a different mission statement.

Media Queries: Navigation Bar Transformations

I recently reviewed Brad Frost’s thoughts on responsive navigation patterns. In terms of mobile widths, I personally have been using the select menu option, utilizing a jQuery script to change out a nav’s unordered list UL for select option tags. I had found it to be a perfect way to utilize a phone’s native function — the act of pulling up the navigation menu a seemingly seamless experience. After reading his cons in that use, I’ve changed my mind.

In a mobile setting, select menu “rolodexes” like in iOS are not a sensible way to display navigation menus because users generally do not know what navigation options there are to begin with. Hence, I agree with him that they are potentially confusing. One must consider the normal, intended use of multiple select menus as a form element that combines many related items. For example in a shopping cart, I want to show color options for a t-shirt. When a user clicks on “select a color”, they expect to find only names of colors like red or blue. In the case of “navigation”, the user might be fairly daunted when presented with many unrelated links in a website. Similarly in my example, someone looking to chose a product color is going to be confused when options like blue hoodies and red jackets appear.

My alternative has usually been the do-nothing approach, essentially restructuring the top nav into a mobile-friendly element. My personal default has usually been a full or half width button with soft gradient, to mimic iOS general styling. The one concern that I have encountered by many clients is that they do prefer the nav to fall at the bottom of each subpage. A jQuery detach/append can certainly do this, but that function is processor intensive and rather clunky with click-happy users. One client was so perturbed that I created an entire mobile version of the site with this layout.

My solution for Urban Bean presents the homepage with just nav and on each page, the nav appears at the bottom.

At the end of the article, Brad linked to an interesting pull down nav solution by Inspect Element which essentially takes a cue from the pull-down-to-update effect by Twitter. I’d call it more of a pull-down-to-reveal since the nav height doesn’t stay anchored atop, rather the page itself pulls down to reveal nav from top to bottom. While the solution is very compelling and presents room for creativity, unfortunately I don’t find the pull down nav to be terribly intuitive. Subducted information from the top of a page tends to imply related content to that page, not to the entire website. Also from a UI perspective, we’re taxing the brain to orient two up-and-down motions. The other motion is iOS Safari’s native inclination to snap the entire browser window when you exceed a page’s maximum scroll.

Facebook introduced the left reveal and it works because natively, iOS apps like to slide progressively right to left. Sliding the current page left to right implies we’ve moved back a step. The home menu is further implied to be a master screen by several important details. First, the menu is generally a dark color and color grades downward, second the current page’s subtle box-shadow floats it atop, and thirdly, the page hasn’t quite moved all the over, implying we’re taking a peek into the master Facebook brain behind everything. A left reveal also lets the thumb do its job of scrolling, only this time for navigation. You could do this with the pull down nav but then you’d be asking the user to track three vertically changing elements all at once. Vertigo would ensue (unless that’s what you want!).

My last observation is that I’ve noticed some designers pushing ridiculously small text scaling for their navigation bars as you move toward smaller screen widths. To keep the horizontal element, they’ll squeeze nav buttons, proportionally might I add, into that 20 to 50 pixel height.

CSS Image Swap from Image Crop

I’m often asked by clients and coding learners how to conceptualize the output of HTML/CSS to front-end. Basically these are first steps to fully understanding what the DOM hierarchy is — or in other words, how the browser interprets the document flow and order.

A client was keen to create a CSS class that would produce a image swap with an image tag in a blog post. He would create two images and insert them into a DIV that would “hide” one. On hover, the other half of the image would appear. He knew such a thing could happen and that two divs would possibly be involved but could not determine how the CSS would do this.

The solution is to put both images into a div, we’ll call swapimage, and assign the second image class swap-target.  Here the HTML5 figure tag can be used in place of the div as it works semantically.

<figure class="swapimage">
<img src="image1.png" alt="First Image." />
<img src="image2.png" class="swap-target" alt="Second Image." />
</figure>

And the CSS:

<style type="text/css">
.swapimage {
 display: block;
 position: relative;
 margin: 0;
 padding: 0;
}
.swap-target {
 position: absolute;
 top: 0;
 left: 0;
 display: none;
z-index: 2;
 }
.swapimage:hover .swap-target {
 display: block; }
</style>

Here swapimage acts as a “container” for the image swap.  Relative position allows the second image to absolutely align “over” the other one (set by z-index).  On swapimage:hover, the target image is set to block.   CSS visibility can be used, but I prefer display in most cases, as the difference being it actually removes the element from the page.

Safari File Upload Hang Up

The HTML Form file input tag has been around for ages but for some reason Safari has had native issues with it since the dawn of the Mac era. I always expect there to be issues that arise in every project but this was certainly was a surprise that put me through the early hours of the night before final client testing.

An Ajax hack is required to force Safari to close the keep alive requests which is better explained by techies at Webkit Bugzilla. The hang effect is basically Safari continuing to show it’s uploading a file and never going anywhere. Sometimes the file will work and go through, especially smaller sizes.

Solutions varied on closing keepalive, telling Safari to move it. Airblade Software offers a good solution which is expanded by this freelancer forum I visited. The script requires Ajax and the forum suggested using the Prototype framework’s Ajax support but that would create conflicts with my existing jQuery code so I grabbed the simple Ajax Request Library by Matt Kruse.  As well, a forum user notes you should call the script before the form, thus document ready is added.

In your body’s form, include onsubmit to the kill function.

<form action="upload.php" enctype="multipart/form-data" method="post" onsubmit="closeKeepAlive();">
<input type="file" name="image" />
<input type="submit" id="upload" name="upload" value="Send " />
</form>

In the head:

<script type="text/javascript" src="js/ajaxrequest.js"></script>
<script type="text/javascript">
/* die safari! */
$(document).ready(function () { 
function closeKeepAlive() {
  if (/AppleWebKit|MSIE/.test(navigator.userAgent)) {
    new Ajax.Request("safari-die.php", { asynchronous:false });	
  }
return true;
}
});
</script>

In the php file

<?php header("connection: close"); ?>

Google Maps Toggle Mashup (outdated)

Update 12/30/12: This method is outdated and I have revised it.

Even I sometimes panic at the thought of acronyms but once you get past the technobabble, they’re just fancy names for simple concepts. “Keyhole Mashup Language” is the open source standard of mapping coordinates that Google adopted after it acquired the former Keyhole geo-mapping company. Like HTML, it involves semantic tags wrapping information. I was recently asked to fix a Google “mash-up” that involved multiple maps (KML layers) that would turn on and off a Google Map via Javascript. The fix solution was, as usual, to rebuild the whole thing using Google’s latest API standards (see samples here).

The basic application of this mash-up is to toggle multiple maps, hence the name. For my fellow urban planners, this allows the public to contrast and compare different layers like bike lanes, parks, and farmer markets without them needing to have any special ArcGIS viewer. Google also allows you to pull a KML layer directly off the Maps website, meaning you can pull live maps that anyone can update. For larger and more complex layers though you might want to have the KML layer on your server to reduce loading time.

The operating map is called the Big Box Tool Kit and features layers of points in the country where communities have opposed various big box corporations. Immediately one can toggle on maps to see how active certain parts of the country are compared to others.

Call the API.

<script type="text/javascript"
    src="http://maps.google.com/maps/api/js?sensor=false">
</script>

Now in global.js or the header…

function initialize() {
 displayMaps();
}

Define attributes of the map (Google’s API controls and style guide is handy) and tell it where to show the Google map, in this case map_canvas.

  function displayMaps() {
	var myLatlng = new google.maps.LatLng(40,-93.8);
	var myOptions = {
	  zoom: 4,
	  center: (myLatlng),
	  mapTypeId: google.maps.MapTypeId.ROADMAP
	}

  	var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

In general the above should just generate the desired Google maps without anything on it. Now we finagle Javascript to output a layer if a form’s checkbox gets checked. There is an if statement for each layer you want. For example the first statement below: if checkbox fruit in formMapControl gets checked, layer1 will show a new Google map using apples.kml. Using form may not be terribly best practices, but the client wanted to use the browser’s native display of checkboxes.

  	if (document.formMapControl.fruit.checked) {

	        var layer1 = new google.maps.KmlLayer('apples.kml');
  		layer1.setMap(map);

  		/* Ensure the new layer does not change the map center or zoom */
  		layer1.set('preserveViewport', true);
	}

  	if (document.formMapControl.dairy.checked) {

  		var layer2 = new google.maps.KmlLayer('cheese.kml');
  		layer2.setMap(map);

  		layer2.set('preserveViewport', true);
	}

}/*this concludes function displayMaps*/
</script>

In the body the map “toggle control box” is the form and the Google map appears in a div called #map_canvas. Use CSS to style as appropriate. If you add checked to one or multiple inputs, it will default display that map layer when the page loads. In the client example link, the form is arranged in a list and position absolute next to the map_canvas, which is styled to be a box with display block. Options of course are endless, you could get fancier by giving the toggle box a transparent background and box-shadow, positioning it over the map. The bare basics follow.

<form name="formMapControl">
   
   <input type="checkbox" name="fruit" value="fruit" onclick="displayMaps();" checked />
      <label class="mapoption">Show Me Fruit!<label></li>
      <input type="checkbox" name="dairy" value="dairy" onclick="displayMaps();" />
      <label class="mapoption">Show Me Dairy!<label></li>

</form>

<div id="map_canvas"></div>

List Sub Categories of Parent Category

I just spent a good Friday resolving something that should be very simple. Of course it’s snowing like crazy so I’m not minding. On the Wake Magazine site I’ve been working on, we have a Blogs category that contains multiple sub categories. It’s a very newspaper-like site with multiple writers and thus multiple voices needing their own blog section. I wanted to list out all those sub categories anywhere in the blog area. I already addressed the magic (or insanity) of wp_list_categories so I won’t go there but my question was basically how do I call forth the parent category in a child category page? The solution was pieced together with some searching of the forums and uses a rare function cat_is_ancestor_of that I had no idea existed. Probably most WordPress run websites do not utilize the category terminology very deeply and so those issues are not often touched on. This solution also conditionally display only if you are on sub category page.

<?php
 foreach((get_the_category()) as $childcat) {
   $parentcat = $childcat->category_parent;
   if (cat_is_ancestor_of($parentcat, $childcat)) : ?>
     <div id="subnav">
     <h4>Insert a title or have it pulled from the parent cat</h4>
     <ul>
     <?php wp_list_categories('orderby=id&show_count=0&title_li=&child_of='.$parentcat); ?>
     </ul>
     </div>
   <?php endif; 
   } ?>

Super Simple Random Image

This super simple piece of PHP code will randomly pull images from a folder that are numbered (ie: 1 through 9).  Technically it’s just any folder with numbered image names.   For TCS I created a folder called gallery in my theme folder and placed images in it 1.jpg, 2.jpg and so forth.

<?php
// Change this to the total number of images in the folder
$total = "9";
// Change to the type of files to use eg. .jpg or .gif
$file_type = ".jpg";
// Change to the location of the folder containing the images
$image_folder = "gallery";
// You do not need to edit below this line
$start = "1";
$random = mt_rand($start, $total);
$image_name = $random . $file_type; ?>

Next this echo will call forth the two locations.

<?php echo "$image_folder/$image_name"; ?>

I actually integrated this into the background CSS to produce a cool random background image effect for the header.

<div id="header" style="background: url('<?php bloginfo('template_directory'); ?>/<?php echo "$image_folder/$image_name"; ?>') center top no-repeat">

Exclude Categories from Post Categories List

The exclude variable in the stand-alone wp_list_categories doesn’t exist for get_the_category when your blog is listing the categories related to that post. So you have to create a custom function to define the categories which output. I found the solution at Technokinetics and adapted it here. Another blog also covers the topic (of course you can define cat_ID instead of cat_name).

Put in your theme. Btw the (‘, ‘) is a separator you can change that will go between the categories.

<span><?php custom_cat_list(', '); ?></span>

Put in functions.php, note the function below uses an && AND operator.

function custom_cat_list($separator) {
      $first_time = 1;
      foreach((get_the_category()) as $category) {
        if ($category->cat_name != 'Music' && $category->cat_name != 'Hipsters') {
          if ($first_time == 1) {
            echo '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . '>'  . $category->name.'</a>';
            $first_time = 0;
          } else {
            echo ' I don't like music or hipsters or you could just leave this blank. ';
          }
        }
      }
    }

Super Simple Featured Box

I’m using this function because I recently created a featured box for TwinCityScene and would like control over its structure.  While the built-in sticky option could suffice for simple CSS sizing, it doesn’t really let me do much with say thumbnails.  I also prefer not to use a heavy plug-in which then we get into the arena of ranking featured posts when honestly I want to keep this site automated.

To do this box, I create a new category called “Featured.” This is an administrative category being merely functional. However I still want to list the post categories that the featured post belongs to (ie: “Music,” “Art”).  So in my index.php (or applicable theme file) I called the loop twice.  In the first I told query_posts to show only 1 post from category 684 which happens to be the new Featured cat.  then the second loop query_posts omits 684 with a negative – sign.   I’m sure there are other ways to customize the loop but I found this to be the most efficient and natural for WordPress instead of a litany of if else statements.

<?php query_posts("showposts=1&cat=684"); ?>
<?php while ( have_posts() ) : the_post() ?>
My structure for the featured box where I used <?php custom_cat_list(', '); ?> to omit the Featured Category from showing up.
<?php endwhile ?>

<?php query_posts("cat=-684"); ?>
<?php while ( have_posts() ) : the_post() ?>
My structure for regular posts where get_the_category lists normally.
<?php endwhile ?>

Integrate Links Into Navigation

If you are using wp_list_categories sometimes you want to manually add HTML/links before and after the categories that are generated in order to preserve the ul list. Similarly, you’d want to bundle the ul tags within an if else statement. Most PHP gurus know this but basically you can use an echo output to generate the needed HTML. I used this for TwinCityScene in adding a home link to the front and social networking buttons to the end. Why would you want to go to the hassle to do this? Accessibility! Special browsers will love you for logically grouping all your links into one ul nav.

<?php 
global $post; 
echo '<ul class="catnav"><li class="cat-item homelink"><a href="/">Home</a>'; 
wp_list_categories('orderby=name&amp;title_li='); 
echo '</li> 
<li class="socnet iconrss"><a title="RSS Feed" href="rss.xml">RSS Feed</a></li> 
<li class="socnet icontw"><a title="Twitter@TwinCityScene" href="http://www.twitter.com/twincityscene">Twitter</a></li> 
<li class="socnet iconfb"><a title="Facebook Fan Page" href="http://www.facebook.com/twincityscene">Facebook</a></li> 
'; } 
else { }; 
?>

The attached CSS follows. Of course it’s a bit gussied up but the main elements are there.

.catnav { background: #000 url('images/bgnav.png') center top no-repeat; clear: both; list-style: none; margin: 0; padding: 0; border-bottom: 1px solid #111; border-top: 1px solid #111; width: 100%; display: block; height: 35px; text-align: center;}
.catnav li.cat-item { color: #555; display: inline; text-align: left; margin: 0 5px 0 0; padding: 10px 0 10px 2px;}
.catnav li.cat-item a { text-shadow: 1px 1px #333; text-transform: uppercase; padding: 0 7px 0 7px; height: 35px; color: #ccc; border-right: 1px solid #333; font: 300 1.3em Helvetica, Arial, sans-serif; letter-spacing: -0.5px; line-height: 1.9em; }
.catnav li:hover a, .catnav li a:hover { text-shadow: 1px 1px #333; color: #fff; text-decoration: underline;}
.catnav li:hover { color: #fff; background: transparent url('images/bghover.png') center top no-repeat;}
.catnav li.homelink { color: #000;}
.catnav li.homelink a { padding-left: 5px; border-left: none; }
.catnav li.homelink:hover a { color: #fff;}

.catnav li.socnet { border: none; float: right; margin: 0 10px 0 10px; padding: 0;}
.catnav li.socnet a { margin: 2px 0 0 0; width: 30px; height: 30px; display: block; text-indent: -999em;}
.catnav li.icontw a { background: transparent url('images/twitter.png') center center no-repeat; }
.catnav li.iconfb a { background: transparent url('images/facebook.png') center center no-repeat; }
.catnav li.iconrss a { background: transparent url('images/rss.png') center center no-repeat; }