Shiny Bash



Shiny Bash

0 1


bash-gradle-angularjs-slides

Slides for Bash 06/11/2013 on Gradle and AngularJS

On Github DavidMcFarland / bash-gradle-angularjs-slides

Shiny Bash

Created by David McFarland and Garth Gilmour using Reveal.js.

About this talk

Outline

  • ~15 mintues on a shiny new build tool.
  • ~15 mintues on a shiny new web framework.

Shiny and new are relative terms both technologies have be about since 2009.

Part 1

Build tools

Tasks

<target name="compile" description="Compile source tree java files">
	<mkdir dir="${build.dir}"/>
	<javac destdir="${build.dir}" source="1.5" target="1.5">
		<src path="${src.dir}"/>
		<classpath refid="master-classpath"/>
	</javac>
</target>

Targets

<project name="Hello World Project" default="greetTheWorld">
	<target name="greetTheWorld" depends="prepare">
		<echo>Hello World!</echo>
	</target>
	<target name="prepare">
		<echo>Preparing to greet the world...</echo>
	</target>
</project>

Simple Maven Build

<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.instil</groupId>
	<artifactId>BuildingWithMaven</artifactId>
	<packaging>jar</packaging>
	<version>0.1</version>
	<name>BuildingWithMaven</name>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

Maven File Convention

Maven repository layout

├── archetype-catalog.xml
├── repository
│   ├── antlr
│   │   └── antlr
│   │   ├── 2.7.2
│   │   │   ├── _maven.repositories
│   │   │   ├── antlr-2.7.2.jar
│   │   │   ├── antlr-2.7.2.jar.sha1
│   │   │   ├── antlr-2.7.2.pom
│   │   │   └── antlr-2.7.2.pom.sha1
│   │   ├── 2.7.6
│   │   │   ├── _maven.repositories
│   │   │   ├── antlr-2.7.6.jar
│   │   │   ├── antlr-2.7.6.jar.sha1
│   │   │   ├── antlr-2.7.6.pom
│   │   │   └── antlr-2.7.6.pom.sha1

Who's using Gradle

Thoughtworks Technology Radar

Gradle - Adopt

Maven - Proceed with caution

Language-based build tools like Gradle and Rake continue to offer finer-grained abstractions and more flexibility long term than XML and plug-in based tools like Ant and Maven. This allows them to grow gracefully as projects become more complex.

Simple Gradle Build

apply plugin: 'java'

group = 'com.instil'
version = 0.1

repositories { mavenCentral() }

dependencies {
	compile 'commons-lang:commons-lang:2.6'
	testCompile 'junit:junit:4.10'
	testCompile 'org.hamcrest:hamcrest-all:1.3'
	testCompile "org.mockito:mockito-all:1.9.5"
	testCompile('com.googlecode.lambdaj:lambdaj:2.3.3') {
		exclude module: 'mockito-all'
	}
}

Additional source sets

sourceSets {
    migration {
        compileClasspath += sourceSets.main.runtimeClasspath
    }
    integrationTest {
        compileClasspath += sourceSets.test.runtimeClasspath
    }
}

dependencies {
    migrationCompile 'net.sourceforge.jtds:jtds:1.3.1'
}

}

Polyglot

Building a jar containing all dependencies

jar {
  from(configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }) 
  {
      exclude "META-INF/*.SF"
      exclude "META-INF/*.DSA"
      exclude "META-INF/*.RSA"
  }
}

Global dependency exclusion

configurations {
    compile.exclude module: 'slf4j-log4j12'
    compile.exclude module: 'servlet-api'
    migrationCompile {
        extendsFrom compile
    }
}

Directed Acyclic Graph

Incremental Build

task transform {
    ext.srcFile = file('mountains.xml')
    ext.destDir = new File(buildDir, 'generated')
    inputs.file srcFile
    outputs.dir destDir
    doLast {
        println "Transforming source file."
        destDir.mkdirs()
        def mountains = new XmlParser().parse(srcFile)
        mountains.mountain.each { mountain ->
            def name = mountain.name[0].text()
            def height = mountain.height[0].text()
            def destFile = new File(destDir, "${name}.txt")
            destFile.text = "$name -> ${height}\n"
        }
    }
}

Run a dropwizard application

task run(type: JavaExec, description: "Start Demo application") {
    classpath project.sourceSets.main.runtimeClasspath
    main = "com.instil.DemoService"
    args = ["server", "./src/main/resources/config_development.yml"]
}

Gradle Wrapper

task wrapper(type: Wrapper, description: 'Generate gradle wrapper') {
    gradleVersion = '1.9'
}

Ant - too flexible

Maven - too strict

Gradle - just right... for now

Part 2

The magical world of AngularJS...

Early DOM manipulation

document.getElementById("printable-content")
document.getElementsByName("box")
document.getElementsByTag("TR")

Early DOM manipulation (cont.)

function findMatchingElements(elements, type) {
    var matchingElements = [];
    if (elements.hasChildNodes()) {
      var child = elements.firstChild;
      while (child) {
        if (child.nodeType === 1 && child.tagName == type) {
          matchingElements += findMatchingElements(child)
        }
        child = child.nextSibling;
      }
    }
    return matchingElements;
}
var printableContentElement =  document.getElementById('printable-content');
var matchingTables = findMatchingElements(printableContentElement, 'TABLE');

Early DOM manipulation (cont.)

What does this print?

<html>
    <head>
        <script>
            function func() {
                var stuff = document.getElementById("myDiv");
                console.log(stuff.childNodes[1].innerHTML);
            }
        </script>
    </head>
    <body onload="func()">
        <div id="myDiv">
            <p>Fred</p>
            <p>Wilma</p>
        </div>
    </body>
</html>

Selectors and event listeners

$( "#printable-content table" ).hide();

$( "#foo" ).bind( "mouseenter mouseleave", function() {
  $( this ).toggleClass( "entered" );
});
document.querySelectorAll("#score>tbody>tr>td:nth-of-type(2)")

MVC and MVVM

Angular MVC

Angular Scopes

Batarang

Two way bindings

+ =
<input type="number" ng-model="number1" placeholder="Enter a number">
<label> + </label>
<input type="number" ng-model="number2" placeholder="Enter a number">
<label> = </label>
{‌{number1 + number2}‌} <!--Angular Markup-->

Todo List

Filter By:
  • get on plane
  • visit tibet
  • find the blue sheep
  • take picture of blue sheep

ng-repeat directive and filters

<div>
    <span>Filter By:</span> 
    <input type="text" ng-model="search" placeholder="filter">
</div>
<div>
    <ul class="unstyled" style="list-style: none">
    <li ng-repeat="todo in todos | filter:search" ng-animate="'animate'">
        <input type="checkbox" ng-model="todo.done" ng-animate="'rotate'">
        <span class="done-"></span>
    </li>
    </ul>
</div>
$scope.todos = [
    {text:'get on plane', done:true},
    {text:'visit tibet', done:false},
    {text:'find the blue sheep', done:false},
    {text:'take picture of blue sheep', done:false}];

Todo list

3 of 4 remaining
  • get on plane
  • visit tibet
  • find the blue sheep
  • take picture of blue sheep

View

<form ng-submit="addTodo()">
    <input type="text" ng-model="todoText"
       placeholder="new todo">
    <input class="btn btn-primary" type="submit" value="add">
    <input class="btn btn-danger" ng-click="removeCompleted()" value="remove completed"/>
</form>

Controller

$scope.addTodo = function() {
    $scope.todos.push({text:$scope.todoText, done:false});
    $scope.todoText = '';
};

$scope.removeCompleted = function() {
    var oldTodos = $scope.todos;
    $scope.todos = [];
    angular.forEach(oldTodos, function(todo) {
        if (!todo.done) $scope.todos.push(todo);
    });
};

Reverse Filter

Reversed Name: hieJ
<input type="text" ng-model="name" placeholder="Enter a name">
<span>Reversed Name: {‌{name | reverse}‌}</span>
filter('reverse', function() {
    return function(input) {
      var out = "";
      for (var i = 0; i < input.length; i++) {
        out = input.charAt(i) + out;
      }
      return out;
    }
  });

Testing

:) Seperation of concerns.

:) Karma a test tool built around AngularJS.

:( Over complex to configure

:( Testing requires preinstalled tools and gems.

Single page application

$routeProvider.when('/demo/upload',
{
	templateUrl: 'partials/upload.html',
	controller: 'UploadCtrl',
	access: access.admin // A customized extension to AngularJS
});

Validation

Dirty Valid
<input type="email" ng-model="user.email" placeholder="Valid email address"/>
<span class="label label-info" ng-show="simpleForm.$dirty">Dirty</span>
<span class="label label-info" ng-show="simpleForm.$valid">Valid</span>

THE END