Development

  • Dogfood Your Products

    Of all of the greatness at the Automattic grand meetup this year in Utah, one of the most impactful moments was Andrew Spittle’s call to do a better job of dogfooding our apps.

    For those who don’t know, dogfooding is the practice of using your own products. This goes a bit beyond simply testing products. Instead, the idea is that a company uses its own product to be able to more fully evaluate it.

    At Automattic we do this by using our own software such as WordPress.com, Jetpack, and CloudUp as well as testing internal only builds of the WordPress mobile apps before they’re released to the public.

    Lost Opportunities

    Andrew’s talk presented the fact that Automatticians used social networks such as Facebook and Twitter much more than they did WordPress when using a certain hashtag — #a8cgm if I recall correctly.

    After Andrew pointed out the disparity in how Automatticians share their experiences, he mentioned that he wondered how many bug reports and UX suggestions we missed out on by not using our own software.

    Wow… That was such a way to put it.

    Making Dogfooding a Priority

    Up until this point I thought I had been dogfooding Automattic’s products. But, the reality was that while I moved my site over to WordPress.com, I wasn’t using much of the functionality on WordPress.com or the WordPress iOS and Android apps that I had installed. :facepalm:

    Starting right away, I began to use all things Automattic much more often. My website is on WordPress.com. I have the beta versions of both the iOS and Android apps installed on my devices. I use Simplenote periodically for taking notes.

    Since making more of an effort to use Automattic products, I have been surprised at how many bugs I have found and reported.

    The beauty is that all it took was to start using our products more, which is the true power of dogfooding. Each bug we find ourselves is an opportunity to give our users a better experience.

    As a developer, it’s very easy to test things how they should work, which is why we often miss bugs. When an entire company dogfoods its prodcuts, you’re getting experience and feedback from all sorts of people which will help find those edge cases and unexpected usage patterns.

    Photo Credit: laffy4k

  • Creating JavaScript Keyboard Shortcuts with jQuery

    I recently added a keyboard shortcut to a project I was working on.

    And while I have used the jQuery Hotkeys plugin for adding keyboard shortcuts recently, I didn’t use a plugin for this project since I only needed a single keyboard shortcut.

    Taking a large bit of inspiration from Krasimir Tsonev, who also documented his solution, I came up with this:

    [javascript]
    (function( $ ) {
    var $doc = $( document );
    $doc.ready( function(){
    $doc.on( ‘keydown’, function( e ){
    if ( ! $( e.target ).is( ‘:input’ ) ) {

    // props rauchg for pointing out e.shiftKey
    if ( 87 == e.which && e.shiftKey ) {
    // `shift` and `w` are pressed. Do something.
    }
    }
    });
    });

    })( jQuery );
    [/javascript]

    Explanation

    First, I create an anonymous function wrapper and invoke it while passing jQuery as a parameter. This allows me to use the $ syntax for jQuery without worrying about collisions with other libraries.

    Then, after the DOM has loaded, I attach a keydown event handler to the document. Before I run any logic though, I check to make sure that we are currently not within any input type. This is important as I don’t want to trigger keyboard shortcuts when a user is typing.

    After the code ensures that we are not in an input, I check to see if both the shift key and w have been pressed. If so, do some magic!

  • Do Yourself a Favor, Turn On Chrome's Warn Before Quitting

    As a developer, keyboard shortcuts are a necessary part of life. And as a web developer, I use several shortcuts within Chrome as well:

    • ? + t: new tab
    • ? + ^ + i: open developer tools
    • ? + shift + {: shift one tab to the left
    • ? + shift + }: shift one tab to the right
    • ? + w: close current tab
    • ? + q: quit Chrome

    And if you’ve used the above shortcuts for any period of time, you’ve likely accidentally quit Chrome when you meant to close the current tab. :facepalm:

    This used to happen for me at least once a week… until I found Chrome’s Warn Before Quitting option.

    Chrome warn before quitting

    This obscure gem can be found under the Chrome menu. When enabled, you will need to hold ? + q to quit Chrome.

  • Copy to Clipboard in Google Chrome Console

    When developing for the web, sometimes I want to JSONify an object to throw into Sublime Text for an easier look or maybe to compare two separate objects.

    While it’s easy to log an object in Google Chrome, the issue I have is easily getting that from the console to Sublime Text.

    After doing a bit of searching, I found that Google Chrome has a copy function that will copy any text to the clipboard.

    Here are a couple of ways that you could use this function:

    To copy any string, simply use

    [javascript]
    copy( "some string here" );
    [/javascript]

    To copy a JSONified object, you could use something like:

    [code lang=javascript]
    copy( JSON.stringify( object ) );
    [/code]

  • Update Backbone Model with No Change Events

    I recently needed to update an array of models to add a “reflowed” attribute to a comment which would act as a flag to show that the comment had been reordered.

    Doing it Wrong

    When I was working through this issue, the first thing that came to mind was that I could update the model attributes myself.

    This is possible with the following syntax.

    [code lang=javascript]
    model.attributes.attribute = value;
    [/code]

    But, this isn’t good software development. So, I trashed that idea.

    The Backbone Way

    The Backbone way to update a model is:

    [code lang=javascript]
    model.set( { attribute: value } )
    [/code]

    But, by default, this will trigger a change event on every changed attribute. For my use case, triggering change events for several models wasn’t necessary.

    Looking into the annotated Backbone source code, I noticed that I could pass in an options array that set silent to true. This makes the model update look like this:

    [code lang=javascript]
    model.set( { attribute, value }, { silent: true } );
    [/code]

  • Get Most Visible Element on a Web Page

    Recently, I was working on updating keyboard shortcuts for o2 and came across a unique shortcut.

    When pressing r, we wanted to open the reply box for the most visible post. When I first started thinking about this requirement, I found myself thinking: “How the hell can I determine what the most visible post is?”

    Attaching to Scroll Event

    One of the first things that crossed my mind was that I could attach to the window scroll event and then update a mostVisiblePost variable as needed. For example, when a scroll event occurs:

    • Get all posts on the page
    • Check which posts are in the viewport
    • Get the offsets for each and try to determine which is most visible.

    I wasn’t quite fond of this method because it could make scrolling janky and seemed prone to error.

    An Alternative Surfaces

    While I was reading Javascript: The Definitive Guide I came across the JavaScript method elementFromPoint(x,y).

    As I thought more about getting the most visible element on the page, I came up with the idea of creating a grid of points that covered the page. I could then get the element at each point and traverse up the DOM to find which post was at that point.

    After thinking through this a bit more, I decided to go for it and came up with the following solution:

    [javascript]
    // Note that Underscores and Backbone are being used here.

    //Let’s create a grid of points in the top half of the viewport.
    var viewPortWidth = $( window ).width(),
    viewPortHeight = $( window ).height(),
    xCoords = _.map( [ .2 , .4, .6, .8 ], function( num, key ){ return num * viewPortWidth; } ),
    yCoords = _.map( [ 0, .1, .2, .3, .4 ], function( num, key ){ return num * viewPortHeight; } );

    /*
    * For each coordiante pair (x,y), get element at point,
    * traverse up to find a post, and add post ID to elems.
    */
    var elems = [];
    _.each( yCoords, function( y ){
    _.each( xCoords, function( x ){
    var element = $( document.elementFromPoint( x, y ) ),
    closest = element.closest( o2Keyboard.threadContainer + ‘.post’ );

    if ( closest.length > 0 ) {
    elems.push( closest.attr( ‘id’ ) );
    }
    });
    });

    // Find most frequent (mode) post ID in elems array.
    // Thanks Matthew Flaschen – http://stackoverflow.com/a/1053865
    if ( elems.length > 0 ) {
    var modeMap = {};

    var maxEl = elems[0],
    maxCount = 1;

    _.each( elems, function( el ){
    if ( modeMap[ el ] == null ) {
    modeMap[ el ] = 1;
    } else {
    modeMap[ el ]++;
    }

    if ( modeMap[ el ] > maxCount ) {
    maxEl = el;
    maxCount = modeMap[ el ];
    }
    });
    }
    [/javascript]

    For the purposes of O2, we defined the most visible post to be in the top 40% of the viewport. So, we created an array of y points from 0-.4 times the viewport height. We then created an array of x points that covered most of the viewport.

    Once we’ve created the xCoords and yCoords arrays, we then loop over these two arrays and get the element at each (x,y) coordinate pair. In this example, we will be creating 20 unique (x,y) coordinate pairs. You can fine tune that for your needs.

    Once we have the element at each point, we traverse up the DOM to see if there is a post. If there is, that post’s ID gets added to an array.

    We then take a mode, essentially finding the post with the most hits, on the elems array and that is the most visible post.

    Questions or Comments?

    If you have any questions or comments about this method, feel free to leave a comment below.

  • Why Concatenate Files in WordPress?

    One of the easiest things that you can do to increase the speed of your website is to concatenate the CSS and JavaScript files that are loaded on your site.

    This only takes a couple of minutes since all you need to do is install a plugin. For this, I have typically used WP Minify, but have also occasionally used Better WP Minify.

    What is Concatenation?

    Sure, I can tell you that concatenation will help speed up your site, and you can easily install a minification plugin… but why does concatenation help?

    First, to understand why concatenation helps, we need to understand what concatenation is.

    Simply, concatenation is the combining of files into one large file.

    For example: Instead of loading many CSS and JavaScript files for the many plugins that your site has enabled, these files would be combined into one large CSS and one large JavaScript file.

    How Does Concatenation Help?

    To understand why concatenating files is beneficial, let’s consider the act of having to bring in many grocery bags.

    Imagine that there are 12 bags in the trunk of your car. You have the option of taking all 12 bags in one trip or taking a trip for each bag.

    If you take all 12 bags in one trip, the trip will likely take a bit longer since you’re carrying more weight. But, if you take multiple trips, then you’re traveling the same distance many many times.

    Arguably, taking all 12 bags in one trip will require more effort but will be faster.

    This is very similar to why concatenation helps speed up your site. Instead of the browser having to take multiple trips to the server to download several JavaScript and CSS files, these files are packaged into just two larger files.

    While these larger files themselves will take a bit longer to download, the browser isn’t having to take multiple trips back to the server to download individual files.

  • #21 – In order to understand recursion, one must first understand recursion.

    Understand Recursion

    I found this amusing since recursion is definitely one of the computer science subjects that I struggled with the most in university.

    I remember having to manually draw stacks on paper to keep track of values and how deep in recursion I was.

    I might have to see how much it costs to print this on a poster!

  • Parse RSS in ExactTarget

    I was recently tasked with migrating a few themes from Mailchimp to Exact Target. While the overall experience I had working with ExactTarget was much less than stellar, I most disliked working with RSS feeds. The whole process of parsing an RSS feed seemed awkward.

    So, in an effort to help others, and because I never want to figure out how to parse RSS for Exact Target again, here is how you can use RSS feeds within your Exact Target templates.

    Create a Content Area

    The method described to me by Exact Target’s support requires that the RSS be stored in a content area within the Exact Target interface. To do this, you will need to create an HTML content area and place the following within it:

    [code]%%before;httpget;1"http://domain.com/rss"%%%5B/code%5D

    This piece of code will fetch the contents of the RSS feed each time the content area is called.

    For example, when we use ContentAreaByName("My Contentsrss_featured"), the RSS is being fetched and stored at that time.

    Parse the RSS Contents

    Actually parsing the RSS feed and getting the desired output was a bit more difficult since Exact Target uses what I believe is a proprietary language named AMPscript.

    Thankfully, the Exact Target support came through with a snippet of code that gave me a good head start. I took that snippet and built the following.

    [code]
    %%[
    Var @xml, @titles, @title, @descs, @desc, @links, @link, @cnt, @dates, @date
    Set @xml = ContentAreaByName("My Contentsrss_featured") /* This line specifies the content area from which the RSS content will be pulled for the email message. */
    Set @titles = BuildRowsetFromXML(@xml,"//item/title",1)
    Set @descs = BuildRowsetFromXML(@xml,"//item/description",1)
    Set @links = BuildRowsetFromXML(@xml,"//item/link",1)
    Set @dates = BuildRowsetFromXML(@xml, "//item/pubDate", 1)

    If RowCount(@titles) > 5 THEN
    SET @rows = 5
    ELSE
    SET @rows = RowCount(@titles)
    ENDIF

    IF @rows >= 1 THEN
    for @cnt = 1 to @rows do
    Set @title = Field(Row(@titles,@cnt),"Value")
    Set @desc = Field(Row(@descs,@cnt), "Value")
    Set @link = Field(Row(@links,@cnt), "Value")
    Set @date = Format(DateParse(Field(Row(@dates,@cnt), "Value")),"MMM d, yyyy h:mm tt")
    ]%%

    <div class="feed-item" style="background:#444;padding:10px 10px 0;margin-bottom:20px;border-left:4px solid #222;"><span style="color:#ffffff;font-size:16px;line-height:20px;margin-bottom:12px;">%%=v(@title)=%%</span>
    <span style="color:#cccccc;font-size:12px;line-height:20px;margin-bottom:12px;">%%=v(@date)=%%</span>
    <a style="text-decoration:underline;font-weight:normal;color:#336699 !important;" href="%%=RedirectTo(@link)=%%">More info…</a>
    </div>

    %%[
    NEXT @cnt
    ENDIF
    ]%%
    [/code]

    This snippet pulls out the Title, Description, Link, and Publication Date for each item in an RSS feed and puts it into what I consider to be an array.

    The next is to then loop through these items, up to 5 rows worth, and get each value. Once we have these values stored in variables we can then place them in templates using the following syntax: %%=v(@varName)=%%.

    The biggest caveat in displaying the information was with inserting a link into the template. Notice that in the above example, %%=RedirectTo(@link)=%%, there is an extra call to RedirectTo. This has to do with the tracking system that Exact Target uses.

    Questions?

    This short article is meant as an introduction into how to parse RSS with Exact Target. I hope that this answers any questions you may have, but if you’d like more information, please leave a comment below and I’ll be sure to help you out.

  • Github Two-Factor Authentication Failed For HTTPS

    About two months ago I first switched to GitHub’s two-factor authentication. Later that day, when I went to push for the first, I had an authentication error and my push failed. I didn’t want to mess with the configuration that day, so I decided to turn off two-factor authentication on GitHub.

    Another Go at Two-Factor Authentication on GitHub

    After a new career move forced that I lock down my computer and my online identities like Fort Knox, I had no choice but to figure out how to get GitHub two-factor authentication working. Yet again, after I configured two-factor authentication on GitHub I had issues pulling from private repositories and pushing/pulling to any repository. So, after digging into the GitHub two-factor authentication blog post on GitHub, I came across this:

    If you are using SSH for Git authentication, rest easy: you don’t need to do anything. If you are using HTTPS Git, instead of entering your password, enter a personal access token. These can be created by going to your application settings page.

    The Solution is Simple

    (more…)

  • Regular Expression Example: Wrapping the Second through Last Words in a Span Element

    For the past week, I have been working on a website for an emergency medical services association. To fit the client’s wishes, the design called for the first word in titles to be blue followed by all other words being red.

    I do not know a way to do this with just HTML, so I decided that I would wrap the second through the last words in a span  element. Then I could add some LESS like this to achieve the color effect I wanted.

    [code lang=css]
    h1,
    h2,
    h3,
    h4,
    h5,
    h6 {
    color: blue;

    span {
    color: red;
    }
    }
    [/code]

    But, how do I get the span element in the titles?

    Using Regular Expressions to Add the Span

    Regular expressions are a very powerful feature of many languages. They allow us to create very complex rules to match phrases in code, words, etc. We can also “capture” parts of these rules, which will prove useful in this example!

    Here is a PHP function with a regular expression example that takes a title and wraps the second through last words in a span  element.

    [code lang=php]
    function span_the_title( $title ) {
    return preg_replace( '#(S+)s(.+)#', '$1 <span>$2</span>', $title );
    }
    [/code]

    Let’s break this down. Notice that I am passing $title in to the function. This is the title that we will actually be filtering in the regular expression. Now take a look at the preg_replace() function. This function takes the following arguments:

    1. A regular expression that is the pattern to search for.
    2. A string to replace matched expressions with. Notice how I used $1 and $2 in the second argument above. This is because I am referencing part of the matched regular expression from the first argument. More on this later.
    3. The third argument is the title, in this case, or really any string.

    Let’s Break It Down

    (more…)

  • Remove Files from Git After Adding/Updating .Gitignore

    I recently inherited a project from a beginning developer. After inheriting the project I realized that, while the developer was using Git to source control the project, the developer had completely forgot to add a .gitignore.

    This meant that I now needed to add a .gitignore file as well as remove files from git that were tracked that shouldn’t have been tracked.

    This isn’t usually a big deal when ignoring a single file or two — The command to remove a single file is:

    git rm --cached <file>
    

    But, since we use Grunt and Sass for our web development projects, there were a ton of files within node_modules  and .sass_cache  as well as .DS_Store files throughout.

    To get around writing multiple commands to ignore all of these files and un-track them, I did this:

    git rm -r --cached .
    git add -A
    git commit -am 'Removing ignored files'
    

    The first command will un-track all files in your git repository.

    The second command will then add all of the files in your git repository, except those that match rules in your .gitignore. Thus, we have un-tracked several files with just two commands.

    Then the last command is to commit the changes, which will just be removed files.

  • Remove .sass-cache and node_modules from Sublime Text

    I’ve recently been playing with Foundation, Sass, and Grunt. And while each of these are powerful tools in their own right, they are quick to clutter up a project.

    Grunt creates a node_modules directory while Sass creates a .sass-cache directory.

    But don’t worry, because lucky users of Sublime Text have a simple fix.

    Add .sass-cache and node_modules to Folder Excludes List

    To exclude a directory from showing up in Sublime’s search and in the sidebar, all you need to do is add it to the folder_exclude_patterns key in your user preferences.

    To do this:

    • Click Sublime Text ? Preferences ? Settings – User
    • Add the snippet below
    {
    "folder_exclude_patterns": [".svn", ".git", ".hg", "CVS", ".sass-cache", "node_modules"],
    }
    

    This line of code should ignore the .sass-cache and node_modules directories as well as common source control directories.

  • Rsync Backup on Ubuntu Server

    I work on some servers at my University. Recently our RAID server went out, which means that we could potentially lose all student and professor data across several of our servers. I was tasked with getting some sort of backup going from our main servers to a local backup server.

    After thinking about how to approach the problem, Dr. Awesome (Terry Griffin) and I decided that Rsync would be a good way to go, at least until we could get another RAID server.

    The Command

    Here is the command that I used:

    sudo rsync -arv -e "ssh" --rsync-path="sudo rsync" user@host:/home /backup
    

    The Command Explained

    Note that I am using sudo on both the local server and remote server. You will need to be in the sudoers file on both machines to use this command. Sudo let’s you run a command as the super user, which essentially means you are awesome and can do anything.

    Next, we have rsync with some options. The rysync command is what is used when you want to do a remote sync. Then the options are explained as follows:

    • a = Archive – This creates a tar of the directory that you want to backup, which allows you to keep permissions, times, etc. in sync.
    • r = Recursive – This option will allow the rsync to copy throughout the target directory.
    • v = Verbose – This option will print give you updates on the screen as the rsync command runs.

    Other Notes

    You can be more specific about what is copied by deciding to put a “/” at the end of a directory or not.

    For example, if you a “/” at the end of the source directory, then rsync will copy the content of that folder. If you don’t put a “/” at the end of the source directory, rsync will copy the source directory and its contents.

    If you put a “/” at the end of the destination directory, rsync will paste the contents into that directory. When you don’t use “/”, rsync will create a directory and paste the contents within that directory.

  • How to Add a Google Map to your Website with Geocoding

    Inserting Google Maps into a website is CRAZY easy! Usually what I would advise someone to do is to:

    1. Go to Google Maps
    2. Search for the address that you want to show on your map
    3. Grab the embed code
    4. Insert embed code in your website

    Could it get any easier? Well, that really depends on what your development needs are. I recently completed a project for a client that owned a mobile BBQ restaurant. This client wanted a map on his website that he could easily update with the location of his mobile smoking pit. I didn’t think it made much sense to make the client do the 4 steps above just to update his map… So I decided to look into Geocoding a google map. This way, all my client had to do to update his map was to login and change the address.

    For those that do not know, geocoding is essentially the process of taking an address and turning that into latitude and longitude coordinates. Google maps has geocoding baked in – FOR FREE!

    Without further ado, below is some code on using geocoding with Google Maps.

    This code goes in the head.

    [code]
    <script src="http://maps.google.com/maps/api/js?sensor=false&quot; type="text/javascript"></script>
    [/code]

    This code can go anywhere in the body.

    [code]
    <div id="map" style="width: 413px; height: 300px;"></div>

    <script type="text/javascript">// <![CDATA[

    var mapOptions = {
    zoom: 16,
    center: new google.maps.LatLng(54.00, -3.00),
    mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    var geocoder = new google.maps.Geocoder();

    var address = ‘3410 Taft Blvd Wichita Falls, TX 76308’;

    geocoder.geocode( { ‘address’: address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
    map.setCenter(results[0].geometry.location);
    var marker = new google.maps.Marker({
    map: map,
    position: results[0].geometry.location
    });
    } else {
    alert("Geocode was not successful for the following reason: " + status);
    }
    });

    var map = new google.maps.Map(document.getElementById("map"), mapOptions);
    // ]]></script>
    [/code]

    You can update the size of the map by changing the width and height values of the #map div. To change the starting zoom level, change zoom. You can change the type of map by changing mapTypeId. And most importantly, you can change the address by changing the value in var address.

    You should be able to plug this code in to your website and be good to go. This code will take the address in var address, Geocode it using Google, and then center the map with a marker at the address specified.

    This is a fairly simple example of Geocoding, but you could take this code and make a map that will dynamically update with user input. In a future post, I will discuss how to integrate Geocoding into WordPress so that you can easily create and edit maps without having to get latitude and longitude coordinates.

  • Youtube UIWebView with Storyboards

    While working on the iMustangs project, we decided that it would be a good idea to include the school fight song. I’m sure we could have found a way to play a .mp3 file, but we decided that it would be best to create a video so that we could display our university logo. What follows is the result of our work in using UIWebView on iOS.

    First Attempt

    Our first attempt was very light on code and pretty simple. I’d like to show this to you by running through a test project. In Xcode, go ahead and start a new single-view application.

    Navigate to the Storyboard in your project. Once you are here, add a web view on top of the current view. Go ahead and stretch the web view to fill the view below. Now, let’s go ahead and connect the web view.

    I like to use the assistant editor when I connect UIWebViews and other objects to outlets and actions. Click the assistant editor button near the top right of Xcode (I am currently using 4.3.1). The assistant editor will show the storyboard beside your class, so that you can easily connect an object to a specific line of code in your .h file.

    Once you’re in assistant editor mode, click the UIWebView and drag it to just below @interface. Let go.

    At this point another dialog should’ve popped that is asking you to name your UIWebView. Go ahead and name it webView (be sure to use correct case).

    uiWebViewScreenShot

    Now, navigate to your ViewController.m file and paste the following code within the viewDidLoad function. You may replace the url with one of your own.

    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"<a href="http://www.youtube.com/embed/XeIKnBDN4To">http://www.youtube.com/embed/XeIKnBDN4To</a>"]]];
    

    At this point, you should be able to run this project in a simulator and see an MSU youtube video, or whatever URL you substituted. This worked fine for us, until we put it on an actual iPhone… (more…)

  • Adding Custom Overlays to iOS MapKit Framework

    Series

    This is part 2 of a 2-part series on how to create custom overlays for the MapKit framework on iOS. View part 1 of this series here.

    Creating Custom Overlay in iOS

    Everything we have done up to this point has been to create the tiles we will use in our project. Now that we have created those tiles, we need to add them to our project.

    For this, we will use a sample project from Apple called Tile Map. I have a working iOS project that uses custom overlay at Github. We are going to copy a few classes from this project, so go ahead and grab the zip-ball and open it in Xcode.

    You will need to copy the following files into your own project:

    • TileOverlay.h
    • TileOverlay.m
    • TileOverlayView.h
    • TileOVerlayView.m

    Be sure to select the box to “Copy items into destination group’s folder.” At this point I am going to assume that you have already created a View Controller for your map. If not, go ahead and create one. In the .m (implementation) file of your map View Controller, we are going to import the TileOverlay.h and TileOverlayView.h files. Your map View Controller should now look something like this:

    (more…)

  • Creating Custom Overlays for iOS MapKit Framework

    I am part of a team developing an iPhone app for Midwestern State University. I am particularly responsible for developing the map that we are going to use for the app. Because I had a lot of detail I wanted to show on our map – Faculty/Commuter/Resident Parking Lots,  labels for different buildings, key points of interest on campus – I began to look into using custom overlays, a large image laid of top of the Google map tiles.

    One of the issues I ran into was a lack of good information on how to integrate custom overlays into an existing iOS project. What follows is the process used to create and integrate custom overlays into an existing iOS app.

    Create Overlay Image

    I knew from the beginning that I would need some graphic of Midwestern State University to serve as a foundation for me to build my overlay image. To get the background image, I:

    • Went go Google Maps
    • Grabbed the embed code for the location I wanted
    • Created a quick HTML document with the embed code in it
    • I changed the size of the iframe to about 4,000 px by 4,000 px
    • I used a plugin for Google Chrome browser that took a screenshot of the entire page

    This gave me a background image that I could put into Photoshop and then build upon. I used 300 PPI and set my image size to about 3,000 px by 4,000 px. With a smaller image size or lower resolution I noticed that I had very jagged edges. You can tweak these image settings to your project.

    Start building your overlay on top of this background image. When you have an overlay image that you are happy with, hide the background, and export your image. I exported my image as a PNG-24 since I had large amounts of blank area on the image.

    Find the Corner Coordinates

    The best way I found to match the corner pixels of the image to coordinates is to:
    (more…)