Creating coffee script
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..57c1ada
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.vagrant/
+.idea/
\ No newline at end of file
diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml
new file mode 100644
index 0000000..94b5e9e
--- /dev/null
+++ b/.idea/watcherTasks.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectTasksOptions">
+    <TaskOptions isEnabled="true">
+      <option name="arguments" value="--map --compile $FileName$" />
+      <option name="checkSyntaxErrors" value="true" />
+      <option name="description" value="Compiles .coffee files into .js files" />
+      <option name="exitCodeBehavior" value="ERROR" />
+      <option name="fileExtension" value="coffee" />
+      <option name="immediateSync" value="true" />
+      <option name="name" value="CoffeeScript" />
+      <option name="output" value="$FileNameWithoutExtension$.js:$FileNameWithoutExtension$.map:$FileNameWithoutExtension$.js.map" />
+      <option name="outputFilters">
+        <array />
+      </option>
+      <option name="outputFromStdout" value="false" />
+      <option name="passParentEnvs" value="true" />
+      <option name="program" value="/usr/local/bin/coffee" />
+      <option name="scopeName" value="Project Files" />
+      <option name="trackOnlyRoot" value="true" />
+      <option name="workingDir" value="$FileDir$" />
+      <envs />
+    </TaskOptions>
+  </component>
+</project>
\ No newline at end of file
diff --git a/dashboard/.gitignore b/dashboard/.gitignore
index 997ca2f..9ea43ee 100644
--- a/dashboard/.gitignore
+++ b/dashboard/.gitignore
@@ -1 +1,2 @@
-.vagrant
\ No newline at end of file
+.vagrant
+.idea/
diff --git a/dashboard/files/test_app/css/map.css b/dashboard/files/test_app/css/map.css
new file mode 100644
index 0000000..b5281fa
--- /dev/null
+++ b/dashboard/files/test_app/css/map.css
@@ -0,0 +1,87 @@
+#map-container {
+    height: 300px;
+}
+
+.grp {
+    margin-bottom: 30px;
+}
+
+.output {
+    position: fixed;
+    height: 80%;
+    width: 600px;
+    /* padding: 20px; */
+    font-size: 10px;
+    overflow: hidden;
+    /* right: 20px; */
+    /* left: 0px; */
+    background-color: #e5e5e5;
+    font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
+}
+
+/*td, th{*/
+    /*width: 30%;*/
+/*}*/
+thead {
+    background-color: #5A5A5A;
+    color: white;
+    border-bottom: 1px solid rgb(39, 39, 39);
+}
+
+tbody:before {
+    line-height:0.5em;
+    content:"-";
+    color:white; /* to hide text */
+    display:block;
+}
+
+
+th {
+    text-align: left;
+    padding: 4px 2px 1px 5px;
+
+}
+
+td {
+    padding: 0 5px;
+    overflow: hidden;
+}
+
+
+table {
+    width: 100%;
+    table-layout:fixed;
+}
+
+
+.ui-widget-header {
+    /*border: 1px solid #e78f08;*/
+    background: #448CB5;
+    /*color: #fff;*/
+    /*font-weight: bold;*/
+}
+
+
+/*.a {*/
+    /*width: 15%;*/
+/*}*/
+
+/*.b {*/
+    /*width: 20%;*/
+/*}*/
+
+/*.c {*/
+    /*width: 20%;*/
+/*}*/
+
+/*.d {*/
+    /*width: 20%;*/
+/*}*/
+
+/*.e {*/
+    /*width: 20%;*/
+/*}*/
+
+/*.f {*/
+    /*width: 5%;*/
+/*}*/
diff --git a/dashboard/files/test_app/css/style.css b/dashboard/files/test_app/css/style.css
new file mode 100644
index 0000000..bc3e70d
--- /dev/null
+++ b/dashboard/files/test_app/css/style.css
@@ -0,0 +1,132 @@
+/* Space out content a bit */
+body {
+    padding-top: 20px;
+    padding-bottom: 20px;
+}
+
+/* Everything but the jumbotron gets side spacing for mobile first views */
+.header,
+.marketing,
+.footer {
+    padding-right: 15px;
+    padding-left: 15px;
+}
+
+.section-header {
+    padding-bottom: 9px;
+    margin: 40px 0 20px;
+    border-bottom: 1px solid #eee;
+}
+
+
+.anchorjs-icon:before {
+    content: "\e144";
+    box-sizing: border-box;
+}
+
+.anchorjs-link {
+    float: left;
+    width: 1em;
+    height: 1em;
+    margin-left: -1.2em;
+    opacity: 0;
+    color: inherit;
+    text-align: center;
+}
+
+.anchorjs-icon {
+    font-size: 60%;
+    vertical-align: .2em;
+}
+
+.anchorjs-link:focus, :hover>.anchorjs-link {
+    opacity: .75;
+    transition: color .16s linear;
+}
+
+.anchorjs-icon {
+    /*font-family: anchorjs-link;*/
+    font-family: 'Glyphicons Halflings';
+    speak: none;
+    font-style: normal;
+    font-weight: 400;
+    font-variant: normal;
+    text-transform: none;
+    line-height: 1;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+}
+
+/* Custom page header */
+.header {
+    padding-bottom: 20px;
+    border-bottom: 1px solid #e5e5e5;
+}
+
+/* Make the masthead heading the same height as the navigation */
+.header h3 {
+    margin-top: 0;
+    margin-bottom: 0;
+    line-height: 40px;
+}
+
+/* Custom page footer */
+.footer {
+    padding-top: 19px;
+    color: #777;
+    border-top: 1px solid #e5e5e5;
+}
+
+.container {
+    width: 80%;
+}
+
+/* Customize container */
+@media (min-width: 768px) {
+
+}
+
+.container-narrow > hr {
+    margin: 30px 0;
+}
+
+/* Main marketing message and sign up button */
+.jumbotron {
+    text-align: center;
+    border-bottom: 1px solid #e5e5e5;
+}
+
+.jumbotron .btn {
+    padding: 14px 24px;
+    font-size: 21px;
+}
+
+/* Supporting marketing content */
+.marketing {
+    margin: 40px 0;
+}
+
+.marketing p + h4 {
+    margin-top: 28px;
+}
+
+/* Responsive: Portrait tablets and up */
+@media screen and (min-width: 768px) {
+    /* Remove the padding we set earlier */
+    .header,
+    .marketing,
+    .footer {
+        padding-right: 0;
+        padding-left: 0;
+    }
+
+    /* Space out the masthead */
+    .header {
+        margin-bottom: 30px;
+    }
+
+    /* Remove the bottom border on the jumbotron for visual effect */
+    .jumbotron {
+        border-bottom: 0;
+    }
+}
\ No newline at end of file
diff --git a/dashboard/files/test_app/index.html b/dashboard/files/test_app/index.html
new file mode 100644
index 0000000..7f722c6
--- /dev/null
+++ b/dashboard/files/test_app/index.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html>
+<head lang="en">
+    <meta charset="UTF-8">
+    <title></title>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css"/>
+    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.css"/>
+
+
+
+    <link rel="stylesheet" href="css/style.css"/>
+    <link rel="stylesheet" href="css/map.css"/>
+
+
+</head>
+<body>
+
+<div class="container">
+    <div class="header clearfix">
+        <!--<nav>-->
+            <!--<ul class="nav nav-pills pull-right">-->
+                <!--<li role="presentation" class="active"><a href="#">Home</a></li>-->
+                <!--<li role="presentation"><a href="#">About</a></li>-->
+                <!--<li role="presentation"><a href="#">Contact</a></li>-->
+            <!--</ul>-->
+        <!--</nav>-->
+        <h3 class="text-muted">User-ALE Examples</h3>
+    </div>
+
+    <div class="col-md-6">
+        <div class="row buttons-grp">
+            <h3 id="buttons" class="section-header">Buttons<a class="anchorjs-link" href="#buttons"><span
+                    class="anchorjs-icon"></span></a></h3>
+
+            <form action="">
+                <div class="form-group">
+                    <a class="btn btn-default" href="#" role="button">Link</a>
+                    <button class="btn btn-default" type="submit">Button</button>
+                    <input class="btn btn-default" type="button" value="Input">
+                    <input class="btn btn-default" type="submit" value="Submit">
+                </div>
+            </form>
+
+            <form action="">
+                <div class="form-group">
+                    <label for="radio-button0">Male</label>
+                    <input class="rdbtn" id="radio-button0" type="radio" name="sex" value="male">
+                    <label for="radio-button1">Female</label>
+                    <input class="rdbtn" id="radio-button1" type="radio" name="sex" value="female">
+                </div>
+            </form>
+        </div>
+        <div class="row">
+            <h3 id="menus" class="section-header">Menus<a class="anchorjs-link" href="#menus"><span
+                    class="anchorjs-icon"></span></a>
+            </h3>
+
+
+            <div class="dropdown">
+                <button class="btn btn-default dropdown-toggle dd-list" type="button" id="dropdownMenu1"
+                        data-toggle="dropdown"
+                        aria-expanded="true">
+                    Dropdown
+                    <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
+                    <li class="dd-item" role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a>
+                    </li>
+                    <li class="dd-item" role="presentation"><a role="menuitem" tabindex="-1" href="#">Another
+                        action</a></li>
+                    <li class="dd-item" role="presentation"><a role="menuitem" tabindex="-1" href="#">Something
+                        else here</a></li>
+                    <li iclass="dd-item" role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated
+                        link</a></li>
+                </ul>
+            </div>
+
+
+        </div>
+        <div class="row query-group">
+            <h3 id="input" class="section-header">Query<a class="anchorjs-link" href="#input"><span
+                    class="anchorjs-icon"></span></a>
+            </h3>
+
+
+            <div class="grp">
+                <form>
+                    <div class="form-group">
+                        <label for="query_name">Query Name</label>
+                        <input id="textbox0" type="text" class="textbox form-control" id="query_name"
+                               placeholder="Query Name">
+                    </div>
+                    <div class="form-group">
+                        <label for="query_country">Query Country</label>
+                        <input id="textbox1" type="text" class="textbox form-control" id="query_country"
+                               placeholder="Query Country">
+                    </div>
+                    <button type="submit" class="btn btn-default">Execute</button>
+                </form>
+            </div>
+
+            <div class="grp">
+                <div class="slider" id="slider0"></div>
+            </div>
+            <div class="grp">
+                <p>
+                    <label for="value">Value range:</label>
+                    <input type="text" id="value" readonly style="border:0; color:#448CB5; font-weight:bold;">
+                </p>
+                <div class="slider" id="slider1"></div>
+            </div>
+
+        </div>
+        <div class="row map-group">
+            <h3 id="map" class="section-header">Map<a class="anchorjs-link" href="#map"><span
+                    class="anchorjs-icon"></span></a></h3>
+
+            <div class="form-group">
+                <input id="map-button0" class="btn btn-default" type="button" value="Paris">
+                <input id="map-button1" class="btn btn-default" type="button" value="Chicago">
+            </div>
+            <div id="map-container"></div>
+        </div>
+
+    </div>
+    <div class="col-md-6">
+        <div class="output">
+            <table>
+                <thead>
+                    <th width="80px">ACTIVITY</th>
+                    <th width="80px">ACTION</th>
+                    <th width="110px">COMPONENT ID</th>
+                    <th width="110px">COMPONENT TYPE</th>
+                    <th width="110px">COMPONENT GROUP</th>
+                    <th width="60px">SOURCE</th>
+                </thead>
+                <tbody>
+
+                </tbody>
+            </table>
+
+        </div>
+    </div>
+    <!--<h3 id="maps" class="section-header">Maps<a class="anchorjs-link" href="#maps"><span class="anchorjs-icon"></span></a></h3>-->
+
+    <!--<h3 id="maps" class="section-header">Maps<a class="anchorjs-link" href="#maps"><span class="anchorjs-icon"></span></a></h3>-->
+
+    <!--<h3 id="maps" class="section-header">Maps<a class="anchorjs-link" href="#maps"><span class="anchorjs-icon"></span></a></h3>-->
+
+    <!--<h3 id="maps" class="section-header">Maps<a class="anchorjs-link" href="#maps"><span class="anchorjs-icon"></span></a></h3>-->
+
+    <!--<h3 id="maps" class="section-header">Maps<a class="anchorjs-link" href="#maps"><span class="anchorjs-icon"></span></a></h3>-->
+
+    <!--<h3 id="maps" class="section-header">Maps<a class="anchorjs-link" href="#maps"><span class="anchorjs-icon"></span></a></h3>-->
+
+    <!--<h3 id="maps" class="section-header">Maps<a class="anchorjs-link" href="#maps"><span class="anchorjs-icon"></span></a></h3>-->
+
+    <!--<h3 id="maps" class="section-header">Maps<a class="anchorjs-link" href="#maps"><span class="anchorjs-icon"></span></a></h3>-->
+    <!---->
+
+
+</div>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js"></script>
+
+<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
+
+<script src="js/map.js"></script>
+<script src="js/logging.js"></script>
+<script src="../../../helper-libs/javascript/userale.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/dashboard/files/test_app/js/logging.js b/dashboard/files/test_app/js/logging.js
new file mode 100644
index 0000000..e82f702
--- /dev/null
+++ b/dashboard/files/test_app/js/logging.js
@@ -0,0 +1,624 @@
+/**
+ * Created by dreed on 3/24/15.
+ */
+$(document).ready(function () {
+    //var ale2 = new userale();
+    var userale = new userale({
+        loggingUrl: '',
+        toolName: 'dave',
+        toolVersion: '2.3',
+        componentGroups: [
+            'map_group',
+            'input_group'
+        ],
+        workerUrl: '../../../helper-libs/javascript/draper.activity_worker-2.1.1.js',
+        debug: true,
+        sendLogs: false
+    });
+
+    userale.register()
+
+    var template = _.template(
+        "<tr>" +
+            "<td class='a'><%- activity %></td>" +
+            "<td class='b'><%- action %></td>" +
+            "<td class='c'><%- component.id %></td>" +
+            "<td class='d'><%- component.type %></td>" +
+            "<td class='e'><%- component.group %></td>" +
+            "<td class='f'><%- source %></td>" +
+        "</tr>"
+    );
+    function log(msg) {
+        var elem = $(template(msg))
+            .appendTo('.output tbody');
+
+        userale.log(msg);
+
+        setTimeout(function () {
+            elem.fadeOut(400, function () {
+                $(this).remove();
+            });
+        }, 2000)
+
+
+    }
+
+
+
+    $('.buttons-grp .btn')
+        .mouseover(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'button_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .mouseout(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOUT',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'button_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .click(function () {
+            var msg = {
+                activity: ale.activities.PERFORM,
+                action: 'CLICK',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'button_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+    $('.rdbtn')
+        .mouseover(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.RADIOBUTTON,
+                    group: 'button_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .mouseout(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOUT',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.RADIOBUTTON,
+                    group: 'button_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .click(function () {
+            var msg = {
+                activity: 'SELECT_DESELECT',
+                action: 'CLICK',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.RADIOBUTTON,
+                    group: 'button_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+    $('.dd-list')
+        .mouseover(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.DROPDOWNLIST,
+                    group: 'dropdown_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .mouseout(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOUT',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.DROPDOWNLIST,
+                    group: 'dropdown_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .click(function () {
+            //console.log($(this).parent().hasClass('open'))
+            var msg = {
+                activity: 'OPEN_CLOSE',
+                action: 'CLICK',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.DROPDOWNLIST,
+                    group: 'dropdown_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+    $('.dd-item')
+        .mouseover(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.LISTITEM,
+                    group: 'dropdown_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .mouseout(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOUT',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.LISTITEM,
+                    group: 'dropdown_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .click(function () {
+            var msg = {
+                activity: ale.activities.PERFORM,
+                action: 'CLICK',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.LISTITEM,
+                    group: 'dropdown_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+    $('.textbox')
+        .mouseover(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.TEXTBOX,
+                    group: 'input_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .mouseout(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.TEXTBOX,
+                    group: 'input_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .click(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'FOCUS',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.TEXTBOX,
+                    group: 'input_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .keypress(function () {
+            var msg = {
+                activity: ale.activities.ALTER,
+                action: 'ENTERTEXT',
+                component: {
+                    id: this.getAttribute('id'),
+                    type: ale.components.TEXTBOX,
+                    group: 'input_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+    $('.map-group .btn')
+        .mouseover(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'map_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .mouseout(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOUT',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'map_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .click(function () {
+            var msg = {
+                activity: ale.activities.PERFORM,
+                action: 'CLICK',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'map_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+    $('.query-group .btn')
+        .mouseover(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'query_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .mouseout(function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOUT',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'query_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .click(function () {
+            var msg = {
+                activity: ale.activities.PERFORM,
+                action: 'CLICK',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.BUTTON,
+                    group: 'query_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['query']
+            };
+            log(msg);
+        });
+
+
+    map
+        .on('mouseover', function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOVER',
+                component: {
+                    id: 'UNK',
+                    type: ale.components.MAP,
+                    group: 'map_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .on('mouseout', function () {
+            var msg = {
+                activity: ale.activities.INSPECT,
+                action: 'MOUSEOUT',
+                component: {
+                    id: 'UNK',
+                    type: ale.components.MAP,
+                    group: 'map_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .on('zoomstart', function () {
+            var msg = {
+                activity: ale.activities.ALTER,
+                action: 'ZOOM',
+                component: {
+                    id: 'UNK',
+                    type: ale.components.MAP,
+                    group: 'map_group'
+                },
+                source: 'unk',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .on('dragstart', function () {
+            var msg = {
+                activity: ale.activities.ALTER,
+                action: 'DRAG',
+                component: {
+                    id: 'UNK',
+                    type: ale.components.MAP,
+                    group: 'map_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .on('dragend', function () {
+            var msg = {
+                activity: ale.activities.ALTER,
+                action: 'DRAG',
+                component: {
+                    id: 'UNK',
+                    type: ale.components.MAP,
+                    group: 'map_group'
+                },
+                source: 'user',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .on('moveend', function () {
+            var msg = {
+                activity: ale.activities.ALTER,
+                action: 'MOVE',
+                component: {
+                    id: 'UNK',
+                    type: 'map',
+                    group: 'map_group'
+                },
+                source: 'system',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+
+    $('.slider')
+        .on("slidestart", function (event, ui) {
+            var msg = {
+                activity: ale.activities.ALTER,
+                action: 'SLIDE',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.SLIDER,
+                    group: 'input_group'
+                },
+                source: 'user',
+                object: 'HANDLE',
+                tags: ['a', 'b']
+            };
+            log(msg);
+        })
+        .on("slidestop", function (event, ui) {
+            var msg = {
+                activity: ale.activities.ALTER,
+                action: 'SLIDE',
+                component: {
+                    id: this.getAttribute('id') || 'UNK',
+                    type: ale.components.SLIDER,
+                    group: 'input_group'
+                },
+                source: 'user',
+                object: 'HANDLE',
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+    $(window)
+        .on("scroll", function() {
+            var msg = {
+                activity: ale.activities.ALTER,
+                action: 'SCROLL',
+                component: {
+                    id: 'UNK',
+                    type: ale.components.WINDOW,
+                    group: 'top'
+                },
+                source: 'unk',
+                object: null,
+                tags: ['a', 'b']
+            };
+            log(msg);
+        });
+
+    ale = {};
+    ale.components =
+    {
+        BUTTON : "button",
+        CANVAS : "canvas",
+        CHECKBOX : "checkbox",
+        COMBOBOX : "combobox",
+        DATAGRID : "datagrid",
+        DIALOGBOX : "dialog_box",
+        DROPDOWNLIST : "dropdownlist",
+        FRAME : "frame",
+        ICON : "icon",
+        INFOBAR : "infobar",
+        LABEL : "label",
+        LINK : "link",
+        LISTBOX : "listbox",
+        LISTITEM: "listitem",
+        MAP : "map",
+        MENU : "menu",
+        MODALWINDOW : "modalwindow",
+        PALETTEWINDOW : "palettewindow",
+        PANEL : "panel",
+        PROGRESSBAR : "progressbar",
+        RADIOBUTTON : "radiobutton",
+        SLIDER : "slider",
+        SPINNER : "spinner",
+        STATUSBAR : "statusbar",
+        TAB : "tab",
+        TABLE : "table",
+        TAG : "tag",
+        TEXTBOX : "textbox",
+        THROBBER : "throbber",
+        TOAST : "toast",
+        TOOLBAR : "toolbar",
+        TOOLTIP : "tooltip",
+        TREEVIEW : "treeview",
+        WINDOW : "window",
+        WORKSPACE : "workspace",
+        // Other is used in conjunction with softwareMetadata in order
+        // to provide a component in which is not currently listed within
+        // the COMPONENT list.
+        OTHER : "other"
+    };
+
+    ale.activities =
+    {
+        ADD : "add",
+        REMOVE : "remove",
+        CREATE : "create",
+        DELETE : "delete",
+        SELECT : "select",
+        DESELECT : "deselect",
+        ENTER : "enter",
+        LEAVE : "leave",
+        INSPECT : "inspect",
+        ALTER : "alter",
+        HIDE : "hide",
+        SHOW : "show",
+        PERFORM: "perform"
+    };
+    //$('#slider1')
+    //    .on("slidestart", function (event, ui) {
+    //        log(this.getAttribute('id') + ' slider start')
+    //    })
+    //    .on("slidestop", function (event, ui) {
+    //        log(this.getAttribute('id') + ' slider stop')
+    //    });
+
+    //document.querySelector('body').addEventListener('click', function(event) {
+    //    //if (event.target.tagName.toLowerCase() === 'li') {
+    //    //    // do your action on your 'li' or whatever it is you're listening for
+    //    //}
+    //
+    //    window.A = event.target;
+    //
+    //    console.log('click', event.target.tagName, event.target)
+    //});
+
+    //$(document).ready(function(){
+    //    $(document).bind('mousewheel', function(e){
+    //        if(e.originalEvent.wheelDelta /120 > 0) {
+    //            log('scrolling up !');
+    //        }
+    //        else{
+    //            log('scrolling down !');
+    //        }
+    //    });
+    //});
+});
\ No newline at end of file
diff --git a/dashboard/files/test_app/js/map.js b/dashboard/files/test_app/js/map.js
new file mode 100644
index 0000000..230139b
--- /dev/null
+++ b/dashboard/files/test_app/js/map.js
@@ -0,0 +1,44 @@
+/**
+ * Created by dreed on 3/24/15.
+ */
+
+$( document ).ready(function() {
+    var map = L.map('map-container').setView([51.505, -0.09], 13);
+
+    L.tileLayer('http://{s}.tiles.mapbox.com/v3/dvreed77.i39bj2hd/{z}/{x}/{y}.png', {
+        attribution: 'Map data &copy; <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://mapbox.com">Mapbox</a>',
+        maxZoom: 18
+    }).addTo(map);
+
+    window.map = map;
+
+    $('#map-button0').click(function() {
+        map.setView(L.latLng(48.8567, 2.3508), 10)
+    });
+
+    $('#map-button1').click(function() {
+        map.setView(L.latLng(41.8369, -87.6847), 11)
+    });
+
+    $(function() {
+        $( "#slider0" ).slider();
+
+
+    });
+
+    $(function() {
+        $( "#slider1" ).slider({
+            range: true,
+            min: 0,
+            max: 500,
+            values: [ 75, 300 ],
+            slide: function( event, ui ) {
+                $( "#value" ).val( ui.values[ 0 ] + " - " + ui.values[ 1 ] );
+            }
+        });
+
+        $( "#value" ).val( $( "#slider1" ).slider( "values", 0 ) +
+        " - " + $( "#slider1" ).slider( "values", 1 ) );
+    });
+});
+
diff --git a/helper-libs/javascript/activities.coffee b/helper-libs/javascript/activities.coffee
new file mode 100644
index 0000000..2157cec
--- /dev/null
+++ b/helper-libs/javascript/activities.coffee
@@ -0,0 +1,10 @@
+teachers =
+  teacher:
+    name: "Andrew Chalkley"
+    hair: "Ginger"
+  teacher:
+    name: "Jim Hoskins"
+    hair: "Ginger"
+  teacher:
+    name: "Pasan Premaratne"
+    hair: "Black"
\ No newline at end of file
diff --git a/helper-libs/javascript/activities.js b/helper-libs/javascript/activities.js
new file mode 100644
index 0000000..8395c0c
--- /dev/null
+++ b/helper-libs/javascript/activities.js
@@ -0,0 +1,22 @@
+// Generated by CoffeeScript 1.9.1
+(function() {
+  var teachers;
+
+  teachers = {
+    teacher: {
+      name: "Andrew Chalkley",
+      hair: "Ginger"
+    },
+    teacher: {
+      name: "Jim Hoskins",
+      hair: "Ginger"
+    },
+    teacher: {
+      name: "Pasan Premaratne",
+      hair: "Black"
+    }
+  };
+
+}).call(this);
+
+//# sourceMappingURL=activities.js.map
diff --git a/helper-libs/javascript/activities.js.map b/helper-libs/javascript/activities.js.map
new file mode 100644
index 0000000..3dd24f9
--- /dev/null
+++ b/helper-libs/javascript/activities.js.map
@@ -0,0 +1,10 @@
+{
+  "version": 3,
+  "file": "activities.js",
+  "sourceRoot": "",
+  "sources": [
+    "activities.coffee"
+  ],
+  "names": [],
+  "mappings": ";AAAA;AAAA,MAAA,QAAA;;AAAA,EAAA,QAAA,GACE;AAAA,IAAA,OAAA,EACE;AAAA,MAAA,IAAA,EAAM,iBAAN;AAAA,MACA,IAAA,EAAM,QADN;KADF;AAAA,IAGA,OAAA,EACE;AAAA,MAAA,IAAA,EAAM,aAAN;AAAA,MACA,IAAA,EAAM,QADN;KAJF;AAAA,IAMA,OAAA,EACE;AAAA,MAAA,IAAA,EAAM,kBAAN;AAAA,MACA,IAAA,EAAM,OADN;KAPF;GADF,CAAA;AAAA"
+}
\ No newline at end of file
diff --git a/helper-libs/javascript/draper.activity_logger-2.1.1.js b/helper-libs/javascript/draper.activity_logger-2.1.1.js
index 24e6156..bfa4a46 100644
--- a/helper-libs/javascript/draper.activity_logger-2.1.1.js
+++ b/helper-libs/javascript/draper.activity_logger-2.1.1.js
@@ -13,7 +13,7 @@
 /*jshint unused:false*/
 function activityLogger(webWorkerURL) {
     'use strict';
-    var draperLog = {version: "2.1.1"}; // semver
+    var draperLog = {version: "3.0.0"}; // semver
     draperLog.worker = new Worker(webWorkerURL);
 
     var muteUserActivityLogging = false,
diff --git a/helper-libs/javascript/userale.coffee b/helper-libs/javascript/userale.coffee
new file mode 100644
index 0000000..cc463ec
--- /dev/null
+++ b/helper-libs/javascript/userale.coffee
@@ -0,0 +1,85 @@
+activities = [
+  'add',
+  'remove',
+  'create',
+  'delete',
+  'select',
+  'deselect',
+  'enter',
+  'leave',
+  'inspect',
+  'alter',
+  'hide',
+  'show'
+]
+
+
+
+console.log('in userale')
+
+extend = (objects...) ->
+  for object in objects
+    for key, value of object
+      objects[0][key] = value
+  return objects[0]
+
+getParameterByName = (name) ->
+  name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]")
+  regex = new RegExp("[\\?&]" + name + "=([^&#]*)")
+
+  results = regex.exec(location.search)
+  console.log(results)
+  results = if results then decodeURIComponent(results[1].replace(/\+/g, " ")) else ""
+
+defaults = {
+  loggingUrl: ''
+  toolName: 'UNK'
+  toolVersion: 'UNK'
+  workerUrl: 'userale-worker.js'
+  debug: true
+  sendLogs: true
+  componentGroups: []
+}
+
+class userale
+  constructor: (options)->
+
+    @options = extend(defaults, options)
+
+    if @options.component_groups.contructor is not Array
+      @options.component_groups = [@options.component_groups]
+
+    @options.version = '3.0.0'
+
+    @worker = new Worker(@options.workerUrl)
+
+  register: () ->
+#    @toolName = toolName
+#    @toolVersion = toolVersion
+#    @component_groups = component_groups
+
+    @sessionID = getParameterByName('USID')
+    @client = getParameterByName('client')
+
+    console.log(@sessionID)
+
+    if !@sessionID
+      @sessionID = @toolName[0..2].toUpperCase() + new Date().getTime()
+      console.warn('USERALE: NO SESSION ID, MAKING ONE UP.  You can pass one in as url parameter (127.0.0.1?USID=12345)')
+
+    if !@client
+      @client = 'UNK'
+      console.warn('USERALE: NO CLIENT, MAKING ONE UP.   You can pass one in as url parameter (127.0.0.1?client=roger)')
+
+    @worker.postMessage({cmd: 'sendBuffer', msg: ''})
+
+  log: (msg) ->
+    for key, value of msg
+      if key is 'component'
+        if value.group in @options.component_groups
+          console.log("#{ value.group } is in component groups")
+        else
+          console.warn("#{ value.group } is NOT in component groups")
+
+
+window.userale = userale
\ No newline at end of file
diff --git a/helper-libs/javascript/userale.js b/helper-libs/javascript/userale.js
new file mode 100644
index 0000000..8d854f9
--- /dev/null
+++ b/helper-libs/javascript/userale.js
@@ -0,0 +1,97 @@
+// Generated by CoffeeScript 1.9.1
+(function() {
+  var activities, defaults, extend, getParameterByName, userale,
+    slice = [].slice,
+    indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  activities = ['add', 'remove', 'create', 'delete', 'select', 'deselect', 'enter', 'leave', 'inspect', 'alter', 'hide', 'show'];
+
+  console.log('in userale');
+
+  extend = function() {
+    var i, key, len, object, objects, value;
+    objects = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    for (i = 0, len = objects.length; i < len; i++) {
+      object = objects[i];
+      for (key in object) {
+        value = object[key];
+        objects[0][key] = value;
+      }
+    }
+    return objects[0];
+  };
+
+  getParameterByName = function(name) {
+    var regex, results;
+    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
+    regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
+    results = regex.exec(location.search);
+    console.log(results);
+    return results = results ? decodeURIComponent(results[1].replace(/\+/g, " ")) : "";
+  };
+
+  defaults = {
+    loggingUrl: '',
+    toolName: 'UNK',
+    toolVersion: 'UNK',
+    workerUrl: 'userale-worker.js',
+    debug: true,
+    sendLogs: true,
+    componentGroups: []
+  };
+
+  userale = (function() {
+    function userale(options) {
+      this.options = extend(defaults, options);
+      if (this.options.component_groups.contructor === !Array) {
+        this.options.component_groups = [this.options.component_groups];
+      }
+      this.options.version = '3.0.0';
+      this.worker = new Worker(this.options.workerUrl);
+    }
+
+    userale.prototype.register = function() {
+      this.sessionID = getParameterByName('USID');
+      this.client = getParameterByName('client');
+      console.log(this.sessionID);
+      if (!this.sessionID) {
+        this.sessionID = this.toolName.slice(0, 3).toUpperCase() + new Date().getTime();
+        console.warn('USERALE: NO SESSION ID, MAKING ONE UP.  You can pass one in as url parameter (127.0.0.1?USID=12345)');
+      }
+      if (!this.client) {
+        this.client = 'UNK';
+        console.warn('USERALE: NO CLIENT, MAKING ONE UP.   You can pass one in as url parameter (127.0.0.1?client=roger)');
+      }
+      return this.worker.postMessage({
+        cmd: 'sendBuffer',
+        msg: ''
+      });
+    };
+
+    userale.prototype.log = function(msg) {
+      var key, ref, results1, value;
+      results1 = [];
+      for (key in msg) {
+        value = msg[key];
+        if (key === 'component') {
+          if (ref = value.group, indexOf.call(this.options.component_groups, ref) >= 0) {
+            results1.push(console.log(value.group + " is in component groups"));
+          } else {
+            results1.push(console.warn(value.group + " is NOT in component groups"));
+          }
+        } else {
+          results1.push(void 0);
+        }
+      }
+      return results1;
+    };
+
+    return userale;
+
+  })();
+
+  window.userale = userale;
+
+}).call(this);
+
+//# sourceMappingURL=userale.js.map
diff --git a/helper-libs/javascript/userale.js.map b/helper-libs/javascript/userale.js.map
new file mode 100644
index 0000000..c393f51
--- /dev/null
+++ b/helper-libs/javascript/userale.js.map
@@ -0,0 +1,10 @@
+{
+  "version": 3,
+  "file": "userale.js",
+  "sourceRoot": "",
+  "sources": [
+    "userale.coffee"
+  ],
+  "names": [],
+  "mappings": "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"
+}
\ No newline at end of file