May 2015
HubspotHack-A-Thon

    Module Description

    A store (or agent) locator using Google Sheets as a datastore.  

    Google Sheet that I used for the demo: https://docs.google.com/spreadsheets/d/1El-pprddUkI27wLNYRh1wQX31DRjya4WOZAOHMa6lMg/edit#gid=0

    I coded this to be able to handle large datasets.  The dataset for the demo has over 10k stores.  Using Sheetrock, I am able to query the sheet for a subset of the data needed based on user's origin (using a geo-bounding box). Once the data is loaded, I use a Haversine formula in Javascript to find the distances to origin for each store and then filter the closest locations.

    Google Spreadsheet Info

    For the spreadsheet, the only required columns are latitude and longitude (must be labeled "lat" and "lng") but of course you will want to add some more interesting info like name, address, hours, etc.  

    I've also added a custom function to the spreadsheet that will geocode the locations for you if you don't have the latitude and longitudes.  To use the function, you must have a column that stores the full address of the location. If either of the lat and lng columns are empty, the function will fill it in:

     hackathon-gsheets

    Templating

    Handlebars.js is used for templating.  After setting up your spreadsheet, simply change the variables in the handlebar template to match your column headings.  To keep things simple, I suggest using simple, lowercase column headings without spaces (e.g. "address1" instead of "Address 1", and "postalcode" instead of "Postal Code", etc.)

    Note: Not affiliated with Starbucks in any way. For demo purposes only! The data powering this demo is old and definitely outdated. Use at your own risk!

    Created by:

    Gary Wong

    Stream Creative

    I handle much of the development efforts at Stream Creative. I also run my own programing firm in Milwaukee, WI where I build all things web and mobile.  I am currently playing with many Javascript toys, including Meteor, Angular.js, Appcelerator Titanium and Cordova.  The entrepreneur in me always love to talk about new ideas and challenges.  Ping me to talk shop or just to connect!

    How It's Built

    Inputs:

    Design Manager

    Custom Module Fields

    Page Edit Screen

    Locator Preview

    Source Code:

    Module HTML

      Module CSS

      /* remove form element styling if you want to use default HS font styling (and respective CSS is loaded ) */ .map_locator { font-size: 16px; } .map_locator input[type=text] { font-size: 16px; border-radius: 5px; border: 1px solid #ccc; width: 100%; line-height: 1.5em; padding: 3px; } .map_locator form { margin: 20px 0; } .map_locator .hs-form-field { margin: 8px 0; } .map_locator .hs-form-field label { margin: 8px 0; display: block; font-weight: bold; } .map_locator input[type=submit] { font-size: 16px; } #map_wrapper { height: {{ widget.map_height|default(300,true) }}px; } #map_canvas { width: 100%; height: 100%; } .map_list_wrapper { overflow-x: auto; } .map_list_wrapper ul { display: block; clear: left; float: left; width: 100%; list-style: none; margin: 0; padding: 0; } .map_list_wrapper ul li { display: block; float: left; cursor: pointer; border: 1px solid transparent; border-top: 1px solid #dedede; width: 31.333%; margin: 1% 1%; } .map_list_wrapper ul li:hover { border: 1px solid #dedede; box-shadow: 0 0 10px 1px #dedede; } .map_list_wrapper ul li:nth-child(3n+1) { clear: both; } .map_list_wrapper .list-label { float: left; margin: 10px 0 0 6px; padding: 2px 3px; width: 10%; max-width: 25px; text-align: center; background: #d2d2d2; color: #ffffff; font-weight: bold; } .map_list_wrapper .list-details { float: left; margin-left: 6px; width: 80%; } .map_list_wrapper .list-details .list-content { padding: 10px; font-size: 14px; line-height: 1.25em; } .map_list_wrapper .list-details .loc-name { font-size: 16px; line-height: 1.5em; text-transform: uppercase; margin-bottom: 8px; } .map_list_wrapper .list-details .loc-dist { margin: 8px 0; } .map_list_wrapper .list-focus { border: 1px solid rgba(0, 165, 222, 0.4); -moz-box-shadow: 0 0 8px rgba(0, 165, 222, 0.4); -webkit-box-shadow: 0 0 8px rgba(0, 165, 222, 0.4); box-shadow: 0 0 8px rgba(0, 165, 222, 0.4); transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s; } .loc-name { /* Picked up by both list and infowindows */ color: #4d4d4d; font-weight: bold; } .map_list_wrapper .loc-directions a { color: white; text-decoration: none; display: inline-block; background-color: #005c3a; padding: 5px 10px; margin: 5px auto; } .map_list_wrapper .loc-directions a:hover { background-color: #337c60; } @media (max-width: 767px) { #map_wrapper { height: 250px; } .map_list_wrapper ul li { clear: both; width: 100%; margin: 0; } }

      Module JavaScript