<LocalOmaha class="org"></LocalOmaha>

LocalOmaha.org

Experiments in Community Building using AngularJS
by Sandi Barr & Matt Payne
3/20/2015
    Updated Fri Mar 20 07:24:03 CDT 2015
AngularJS App
AngularJS App

About Us

We want to tell you about

  1. Experiments in building community
    1. An idea from Des Moines
    2. LocalOmaha.org -- helping Omaha Local Independent Business Alliance
  2. Screen scraping made easy
    1. Java's httpunit.sf.net, jtidy, dom4j, and xpath
    2. nokogiri! Thanks Andy Neely (@RavingLogic)
    3. Want to try nokogiri in a browser? ScraperWiki.com
  3. Our Angular app
  4. Simple Spring Boot tools: SpringBootHackyDemo
  5. Summary of challenges for you to try at home

Community building

Des Moines style!

@DsmWebGeeks

  1. Coder Dojos -- a project that takes one to four meetings
  2. Meeting starts with small lecture about the code and the challenges
  3. People pair, tripple, or quad while working on the challenges
  4. When the timebox is over, there are round robin discussions of the work
  5. Pull requests to the organizer's repository

Changes we wanted to try

  1. Just dojos instead of lectures
  2. Flipping our meetings
      • CodeSchool.com
        Phone cat tutorial
  3. Whole lot of cloning going on
  4. BitBucket.org lets you start a private project then make it public
  5. Freedom to experiment, explore, and do things without the engineering discipline of work
  6. Emphasis on improvisation

Tina Fey's Improv Rules

  1. Yes
  2. Yes, and...
  3. Make statements
  4. No mistakes

LocalOmaha.org experiment

  1. Kicked off 1/20/15
  2. Sandi -- software architect and community builder
  3. Matt -- Announcement at Omaha Java Users' Group (OJUG.org)
  4. The Flipping Experience
    • Tried flipping instead of @DsmWebGeeks into lecture
    • Did not work as well. People are busy.
  5. Dojo at UNOCEC: Saturday 2/7/15 Noon – 5pm.
    • Sandi & Nick -- Browserify
    • Michell & Matt -- From scratch with AngularSeed
    • Abby & Ross -- Server side with Sinatra
  6. Dojo at Omaha Coding Women: Monday 2/23/15 6pm - 8pm
    • Heather & Cece
    • Matt & Chad
  7. Dojo at Aviture: Thursday, 3/5/15 6:00 PM to 8:00 PM
    • Sandi & Art
    • Matt & Ross

Cool things from the Dojos

Take aways -- lessons learned

  1. New People!
  2. New Pairing experiences
  3. Able to "play"
  4. New Coding Technology -- Browserfy

So, we want you to try

  1. Pair programming at meetings
    1. To code
    2. To learn a new technique -- e.g. browserify
  2. Forking and sending pull requests
  3. Play with new technology
  4. Listen for suggestions -- e.g. Nokogiri

Please Remember

  1. Can't get everything you want done in a dojo
  2. two hours is not that long
  3. following up on ideas is tricky -- SQUIRREL!

Screen Scraping Made Easy

  1. HTMLUnit.sf.net, JTidy, dom4j, xpath -- chaos!
  2. Many thanks to Andrew Neely, @RavingLogic, for suggesting nokogiri!
  3. you should go to his talks!!

Let's scrape

1    require 'nokogiri'
2    require 'open-uri'
3    require_relative 'store' # Many thanks Carl Z!
5    DIRECTORY='http://shoplocalomaha.com/Directory'
7    lstStores=[]
8    dir_html = Nokogiri::HTML.parse(open(DIRECTORY))
9    id=1
10   dir_html.css('a.open_profile_page').each do |merchant_link|
11      profile_url=merchant_link.attr('href')
12      profile_html=Nokogiri::HTML.parse(open(profile_url))
13      name=profile_html.css('h2.title').text
14      category=profile_html.css('p.category_name').text
15      address=profile_html.css('p.address').text
16      phone=profile_html.css('p.phone').text
17      facebook=profile_html.css('a.facebook')
20      storeUrl=profile_html.css('p.site')
21      storeUrl=storeUrl.text if !storeUrl.nil?
23      lstStores << Store.new(id,name,profile_url, category,address,phone,facebook,storeUrl)
27      id=id+1
28   end

Saving the output as JSON

31	output = File.open("stores.json", "w")
32	output <<  lstStores.to_json
33	output.close
34	  
35	puts "Normal termination."

LocalOmaha.org/app

the angular app

Where I Started

"angular-seed" project

  • Bundle AngularJS components with bower/npm
  • Undesirable/unmaintainable list of script includes

index.html

<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-filter/dist/angular-filter.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="app.js"></script>
<script src="latlon/latlon.js"></script>
<script src="localOmaha/local.omaha.js"></script>
<script src="localOmaha/local.omaha.business.list.js"></script>
<script src="localOmaha/local.omaha.business.thumbnail.js"></script>
<script src="localOmaha/local.omaha.resource.js"></script>
<script src="localOmaha/local.omaha.service.js"></script>
<script src="components/version/version.js"></script>
<script src="components/version/version-directive.js"></script>
<script src="components/version/interpolate-filter.js"></script>
  • Prototyping to get the job started
  • AngularJS dependency injection
  • Global functions for non Angular functionality

latlon.js
function getDistanceFromCoords (from, to, decimals) {
    ...
}

function getBearingFromCoords(from, to){
    ...
}

Browserify with Nick Nisi

index.html
<script src="dist/app.js"></script></body>
  • app.js
    require('angular');
    require('angular-route');
    require('angular-filter');
    require('angular-resource');
    require('angular-sanitize');
    require('./localOmaha');
    require('./latlon/index');
  • desirable === CommonJS require

    • The Angular components became JavaScript modules.
    • We included them with require.

    localOmaha/index.js
    var app = angular.module('localOmaha');
    
    app.controller('localOmahaBusinessList', require('./local.omaha.business.list'));
    app.controller('localOmahaCompass', require('./local.omaha.compass'));
    
    app.directive('localOmahaBusinessThumbnail', require('./local.omaha.business.thumbnail'));
    
    app.factory('localOmahaResource', require('./local.omaha.resource'));
    app.factory('localOmahaService', require('./local.omaha.service'));
    app.factory('localOmahaUserLocation', require('./local.omaha.user.location'));
    
    

    Directives are defined as modules
    module.exports = function() {
      return {
        restrict: 'E',
        templateUrl: 
          'js/localOmaha/local.omaha.business.thumbnail.html',
        scope: {
          ...
        },
        controller: function($scope) {
          ...
        }
      };
    };

    latlon module

    latlon/index.js
    exports.getDistanceFromCoords = function(from, to, decimals) {
        ...
    };
    exports.getBearingFromCoords = function(from, to) {
        ...
    };

    Using the module in an AngularJS controller
    var latlon = require('../latlon');
    ...
    latlon.getDistanceFromCoords($scope.userLocation, 
      businessLocation)
    latlon.getBearingFromCoords($scope.userLocation, 
      businessLocation)

    Flexbox

    with Art Doler

    • Define the flex container
    • Allow wrapping for _really_ narrow viewports
    • Justify the content
    • Align to the baseline
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    align-items: baseline;
    

    Easy Peasy!

    AngularJS app

    Git Patch Mode

    $ git add -p
    diff --git a/LocalOmahaWebapp/app/assets/styles.css b/LocalOmahaWebapp/app/assets/styles.css
    index a4fbbbb..88672d5 100644
    --- a/LocalOmahaWebapp/app/assets/styles.css
    +++ b/LocalOmahaWebapp/app/assets/styles.css
    @@ -1,18 +1,23 @@
     #compass-business {
         float: left;
    -    width: 80%;
    +    width: 75%;
         padding: 0.5em;
    }
    
     #close-compass {
         float: right;
    -    width: 8%;
    +    width: 15%;
         font-size: 1.5em;
    +    text-align:right;
         cursor: pointer;
    }
    }
    Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]? y
    

    Spring Boot!

    1. Spring Boot is new with Spring 4
    2. Lots of conventions.
    3. Allows embedded web servers (jetty and tomcat)
    4. Simple example:SpringBootHackyDemo
    5. Already built in LocalOmaha.org/SpringBoot
      • It is only a 23M "fat" jar :-)

    Summary of Challenges to try at home

    1. Do something with local data
    2. Get permision from your version of the OL!BA to scrape their website
    3. Build a json file using LocalOmahaNokogiriScraperMatt and try out LocalOmahaWebapp
    4. Work people through the github/bitbucket fork, commit, push, pull request workflow
    5. Get your java pals to get hot reloading working for SpringBootHackyDemo (and send Matt a pull request please)
    6. Try out pair programming http://www.PairProgramWith.me/
    7. Remember the user groups do not have to be just like work.
      1. Remember Tina Fey's rules of improv: Yes, Yes and..., Make statements, No mistakes
      2. "Master your instrument, Master the music, and then forget all that *!xy!@ and just play." -- Charlie Parker

    Many thanks to:

    1. Aviture
    2. @Aviture
    3. Omaha Coding Women
    4. @OmaCodingWomen
    5. UNO Community Engagement Center
    6. @UNOCEC

    -30-