On Github fmitchell / whatilearned
Created by Fredric Mitchell / @fredricmitchell
Web Development Manager at Orbit Media Studios
Drupal, DRY / KISS, Strat. Comm., Graphic Novels
Javascript, Patience, Spanish
I've always enjoyed discovery through blogs, Hacker News, Sitepoint, PHP Weekly, etc.
I seem to never have the time.
A developer competition engaged my ego, within timed parameters, to build something while allowing me to reach outside my comfort zone.
http://developers.jotform.com/competition/
Something that doesn't require a lot of explanation.
Something that incorporates libraries I've read about.
Make a map.
Play with Leaflet.js.
Four weeks +wife, kids (life) +learning something new = 5 hours / week
Keep technical debt small.
{ "require": { "jotform/jotform-api-php": "dev-master", "mustache/mustache": "~2.1", "willdurand/geocoder": "~2.3", "ext-mongo": "*", "slim/slim": "2.*" }, "autoload": { "classmap": ["src/"] } }
Simple way to map urls to callbacks.
http://www.slimframework.com/
// Load composer libraries. require 'vendor/autoload.php'; $app = new \Slim\Slim(array( 'debug' => FALSE )); $app->get('/', function() use ($app) { $app->render('step1.php'); }); // more steps... $app->run();
http://getbootstrap.com/
<!-- head --> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"> <!-- /head --> <!-- body --> <!-- some stuff --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> <!-- /body -->
http://mustache.github.io/
class JotMapMustache extends Mustache_Engine { public function __construct() { // Mustache setup. $mustache_options = array( 'loader' => new Mustache_Loader_FilesystemLoader(dirname(dirname(__FILE__)).'/views'), 'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(dirname(__FILE__)).'/views/partials'), ); parent::__construct($mustache_options); } }
Alternative to relying on Slim Views
Follow docs and examples of how to work with Jotform services.
http://developers.jotform.com/libraries
https://github.com/jotform/jotform-api-php
http://developers.jotform.com/integrations/
try { $jotformAPI = new JotForm($key); } catch (Exception $e) { } // Check if any forms return. if ($forms = $jotformAPI->getForms()) { // do some stuff }
http://geocoder-php.org/
// Setup geocoder. $adapter = new \Geocoder\HttpAdapter\CurlHttpAdapter(); $geocoder = new \Geocoder\Geocoder(); $chain = new \Geocoder\Provider\ChainProvider( array( new \Geocoder\Provider\GoogleMapsProvider($adapter), ) ); $geocoder->registerProvider($chain); // Try to geocode. try { $geocode = $geocoder->geocode($address); $longitude = $geocode->getLongitude(); $latitude = $geocode->getLatitude(); // do more stuff... }
http://www.mongodb.org/
https://mongolab.com/
// Mongo URI. $mongo_uri = "mongodb://foo:bar@ds00000.mongolab.com:43338/jotmap"; // Setup Mongo for storing already geocoded submissions. $uriParts = explode("/", $mongo_uri); $dbName = $uriParts[3]; // Attempt to connect to mongo database. try { $client = new MongoClient($mongo_uri); $db = $client->$dbName; $mongo_submissions = $db->submissions; } catch (Exception $e) { }
Let's review, in greater detail, some of the parts to make it work.
{{> pagetitle }} <div id="loginresults"></div> <button id="jotformlogin" class="btn btn-success btn-lg">Authorize JotMap</button> <h3>OR</h3> <form id="step1form" role="form" action="/step2" method="get"> <div class="input-group"> <input type="text" class="form-control input-lg" id="jotformAPIKey" placeholder="Enter API Key" name="jotformapi"> <span class="input-group-btn"> <button type="submit" id="jotmapstep1" class="btn btn-success btn-lg">Next ››</button> </span> </div> </form> <script> mixpanel.track('Step1 viewed', {'page name' : document.title, 'url' : window.location.pathname, 'parameters' : window.location.search.replace( "?", "" )}); mixpanel.track_forms("#step1form", "Step1 form submission"); $("#jotmapstep1").click(function() { mixpanel.track("Step1 clicked"); }); </script>
// Mustache template loading. $m = new JotMapMustache; $page = $m->loadTemplate('page'); // Hash $hash = array( 'pagetitle' => 'Enter JotForm API Key', 'step' => 1, 'jotformauth' => TRUE, 'sidebar-hidden' => TRUE, ); echo $page->render($hash);
// Go through each submission to geocode. // Based on quick testing, usage of JotForm. foreach ($submissions as $submission) { // Setup variables. $id = $submission['id']; $form_id = $submission['form_id']; $address_answer = $submission['answers'][$jotaddress]['answer']; $label_answer = $submission['answers'][$jotlabel]['answer']; $address = (is_array($address_answer)) ? implode(', ', $submission['answers'][$jotaddress]['answer']) : $address_answer; $name = (is_array($label_answer)) ? implode(' ', $submission['answers'][$jotlabel]['answer']) : $label_answer; // Build Mongo query parameters. $query = array( 'id' => $submission['id'], 'form_id' => $submission['form_id'] ); // See if record is already in db. $existing = (isset($mongo_submissions) && is_object($mongo_submissions)) ? $mongo_submissions->findOne($query) : null; // More stuff. }
// mapdata.mustache <script> {{> mapjs }} {{# markerdata }} {{> markerjs }} {{/ markerdata }} var group = new L.featureGroup([{{marker_ids}}]); map.fitBounds(group.getBounds()); </script> // mapjs.mustache var map = L.map('map'); L.tileLayer('//{s}.tile.cloudmade.com/{{cloudmade_api_key}}/998/256/{z}/{x}/{y}.png', { attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>', maxZoom: 18 }).addTo(map); // markerjs.mustache var {{marker_id}} = L.marker([{{lat}}, {{long}}]).addTo(map); {{marker_id}}.bindPopup("{{label}}");
There will be critics, late nights, and not perfect implementations in your first implementation.
The point is to learn, not hate.
The trade off of KISS is that user needs are complex.
Must decide, within the budget (time, cost) that you have, what will be Phase 2, 3, etc.
Allows for alternative opinions and approaches.
Possibly gives you uses for soft launch.
Inspires others to keep trying.
Contribute to the community (patches, pull requests).
Learning on your own time, by doing, is magical.
jotmap.jotform.io
github.com/fmitchell/jotmap
Slides: brightplumbox.com/whatilearned
Slides Repo: github.com/fmitchell/whatilearned
Feedback: joind.in/talk/view/10066