Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="[Trail Traffic Counter Analysis and Reporting]">
  <title>File Upload, Analysis and Reporting</title>
  
  <!-- Styles -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
  <link href="assets/js/google-code-prettify/prettify.css" rel="stylesheet">
  <link href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.min.css" rel="stylesheet" type="text/css" />
  <!-- JavaScript -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
  <script src="js/bootstrap.min.js"></script>
  <script type="text/javascript" src="https://www.google.com/jsapi"></script>
  <script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['table','corechart', 'bar']}]}"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
  <script src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js"></script> 
</head>
<body>
  <div class="container">
    <div id="content">
    <!-- Set up the Navigation Tabs -->      
      <ul id="tabs" class="nav nav-tabs" data-tabs="tabs">
        <li class="active"><a href="#select" data-toggle="tab">Start Here</a> </li>
        <li><a href="#preview" data-toggle="tab">Preview</a> </li>
        <li><a href="#refine" data-toggle="tab">Refine</a> </li>
        <li><a href="#report" data-toggle="tab">Report</a> </li>
        <li><a href="#help" data-toggle="tab">Help</a> </li>
      </ul>
      <div id="my-tab-content" class="tab-content">
      <!-- Select Tab -->        
        <div class="tab-pane active" id="select">
          <br/>
          <p>Trail Traffic Counter Analysis and Reporting Tool.</p>
          <form class="form-horizontal">
            <div class="form-group">
              <div class="col-lg-6 col-sm-6 col-12">
                <p>Select The File You Wish To Analyze and Timezone for sensor's clock</p>
                <div class="input-group">
                  <span class="input-group-btn">
                    <span class="btn btn-primary btn-file">
                      Browse&hellip; <input type="file" id=files multiple="false">
                    </span>
                  </span>
                  <input type="text" class="form-control" readonly>
                </div>
                <span class="help-block">
                  Your data is private.  Nothing is uploaded or saved in this process.
                </span>
                <span>
                  <form role="form">
                    <label class="radio-inline" id="timezone">
                      <input type="radio" autocomplete="off" name="optradio" value="1" checked>UTC Time
                    </label>
                    <label class="radio-inline">
                      <input type="radio" autocomplete="off" name="optradio" value="0">Local Time
                    </label>
                  </form>
                </span>
              </div>
            </div>
            <button id=upload type="button" class="btn btn-primary">Start</button>
          </form>
        </div>
      <!-- Preview Tab -->  
        <div class="tab-pane" id="preview">
          <h4> Header information:</h4>
          <div class="row">
            <div class="col-md-6">
              <p id="header0">This tab will let you preview the file contents once loaded.</p>
              <p id="header1"></p>
              <p id="header2"></p>
              <p id="header3"></p>
              <p id="header4"></p>
              <h4> Recorded Events:</h4>
              <div class="datapoints"></div>
            </div>
            <div class="drop-dialog">
              <div class="col-md-6">
                <p>Trim the file below then click on the "Refine" tab to continue</p>
                <div class="form-group">
                  <label for="topDrop">Number of Rows to Drop from the Top:</label>
                  <select class="form-control" id="topDrop">
                    <option>0</option>
                    <option>1</option>
                    <option>2</option>
                    <option>3</option>
                    <option>4</option>
                    <option>5</option>
                    <option>6</option>
                    <option>7</option>
                    <option>8</option>
                    <option>9</option>
                    <option>10</option>
                  </select>
                  <label for="bottomDrop">Number of Rows to Drop from the Bottom:</label>
                  <select class="form-control" id="bottomDrop">
                    <option>0</option>
                    <option>1</option>
                    <option>2</option>
                    <option>3</option>
                    <option>4</option>
                    <option>5</option>
                    <option>6</option>
                    <option>7</option>
                    <option>8</option>
                    <option>9</option>
                    <option>10</option>
                  </select>
                </div>
              </div>
            </div>
          </div>
        </div>
      <!-- Refine Tab -->
        <div class="tab-pane" id="refine">
          <p id="startTime">This tab will help you clean up the data once it is populated.</p>
          <p id="endTime"></p>
          <form class="form-inline">
            <div class="form-group">
              <label for="cityInput">City</label>
              <input type="text" class="form-control" id="cityInput" placeholder="City Name">
            </div>
            <div class="form-group">
              <label for="stInput">State</label>
              <select class="form-control" id="stInput">
                <option>NC</option>
                <option>SC</option>
                <option>VA</option>
                <option>KY</option>
              </select>
            </div>
            <button type="button" id="weatherButton" class="btn btn-primary">Get Weather</button>
          </form>
          <br/>
          <div id="table_div"></div>
          <br/>
          <div class="form-buttons">
            <p> Select the level of filtering </p>
            <form role="form">
              <label class="radio-inline">
                <input type="radio" autocomplete="off" id="noFilter" name="optradio" checked>None
              </label>
              <label class="radio-inline">
                <input type="radio" autocomplete="off" id="modFilter" name="optradio">Moderate
              </label>
              <label class="radio-inline">
                <input type="radio" autocomplete="off" id="highFilter" name="optradio">High
              </label>
            </form>
          </div>
        </div>
      <!-- Report Tab -->
        <div class="tab-pane" id="report">
          <h4>Trail Traffic Report</h4>
          <p id="reportSubtitle">This is where the final report goes.</p>
          <div id="chart_div"></div>
          <br/> 
          <div id="table2_div"></div>
          <br/>
          <div class="row">
            <div class="col-md-6">
              <div class="textarea">
                <form role="form">
                  <div class="form">
                    <label for="comment">Comment:</label>
                    <textarea class="form-control" rows="5" id="comment"></textarea>
                  </div>
                </form>
              </div>
            </div>
            <div class="col-md-6"></div>
          </div>
        </div>
      <!-- Help Tab -->
        <div class="tab-pane" id="help">
          <h4>Help</h4>
          <p> Send me a note describing your question, I will get back to you within 12 hours with an answer. </p>
            <a class="btn btn-primary" type="button" href="mailto:chip@seeinsights.com?Subject=Help%20Request">Send Mail</a>
        </div>
      </div>
    </div>
  </div>
</body>
</html>
.btn-file {
    position: relative;
    overflow: hidden;
}
.btn-file input[type=file] {
    position: absolute;
    top: 0;
    right: 0;
    min-width: 100%;
    min-height: 100%;
    font-size: 100px;
    text-align: right;
    filter: alpha(opacity=0);
    opacity: 0;
    outline: none;
    background: white;
    cursor: inherit;
    display: block;
}
  .bold-border {
    border: 3px solid black;
  }
input[readonly] {
  background-color: white !important;
  cursor: text !important;
}
 
// File and Program Variables
var fileInput = $('#files');
var uploadButton = $('#upload');  
var refreshFlag = true;  // Keeps track of whether we need to refresh results
var datapoints = [];  // Array where the data points are stored (no header)
var filteredDatapoints = []; // This is where the filtered data points will go
var url = "http://api.wunderground.com/api/d527f77e6c685457/";  // Weather Underground URL with my API key
var daysCovered = [];  // Index of unique days covered
var daysCoveredIndex = 0;  // Keeps track of where we are in the index of days covered
var weatherData = [];  // Stores the weather for the daysCovered
var delayValue = 0;     // What is the value of the delay for the data set
var data = new google.visualization.DataTable();  // Data table and column headers for reporting
data.addColumn('string', 'Day');
data.addColumn('number', 'Morning');
data.addColumn('number', 'Afternoon');
data.addColumn('number', 'Evening');
data.addColumn('number', 'Night');
data.addColumn('number', 'Total');
data.addColumn('string', 'Weather');
var chartdata = new google.visualization.DataTable();  // Data table and column headers for chart
chartdata.addColumn('string', 'Day');
chartdata.addColumn('number', 'Morning');
chartdata.addColumn('number', 'Afternoon');
chartdata.addColumn('number', 'Evening');
chartdata.addColumn('number', 'Night');
// We will be using the Google Visualization API for table and charts: https://developers.google.com/chart/
var table = new    google.visualization.Table(document.getElementById('table_div'));
var table2 = new   google.visualization.Table(document.getElementById('table2_div'));
var chart = new    google.visualization.ColumnChart(document.getElementById('chart_div'));
// Event handler for the start function
uploadButton.on('click', function() {
  refreshFlag = true;
  if (!window.FileReader) {
    alert('Your browser is not supported');
  }
  var input = fileInput.get(0); 
  // Create a reader object
  var reader = new FileReader();
  if (input.files.length) {
    var textFile = input.files[0];
    reader.readAsText(textFile);
    $(reader).on('load', processFile);  // File uploaded
    $('h4').show();   // Now we can show the interface elements
    $(".form-inline, .form, .form-buttons, .drop-dialog").show();
    $('#table_div, #chart_div,#table2_div').show();
  } 
  else {
    alert('Please choose a file and press "Start" before continuing');
   } 
});
// This is the function that processes the file we upload and provides the preview
function processFile(e) {
  datapoints = [];  // clear the datapoints array
  data.removeRows(0,data.getNumberOfRows());  // Clear the data visualzation tables
  chartdata.removeRows(0,chartdata.getNumberOfRows());
  var file = e.target.result, results;
  var fileOffset = 0;
  var tz = "";
  var c = "";
  if ($('#timezone input:radio:checked').val()) {
    tz=" UTC";
  }
  if (file && file.length) {
    results = file.split("\n");
    // Here is where we will find the right offset for the last dataset (if multiple sets in file)
    for (i=0; i< results.length; i++) {
      c = results[i];
      if (c.substr(0,5) === "Trail") {
        fileOffset = i;
      }
    }
    console.log("fileOffset =" + fileOffset);  // Debug line to show where the start of the last data set resides
    // Now we will have to use the fileOffset to report from the last set and create the datapoints array
    $('#tabs a[href="#preview"]').tab('show'); // Move the focus to the Preview Tab
    $('#header0').html(results[0+fileOffset]);
    $('#header1').html(results[1+fileOffset]);       
    $('#header2').html(results[2+fileOffset]);  
    // Get the Delay value while we are here
    c = results[3+fileOffset];
    $('#header3').html(c);
    var pos = c.indexOf("=")+1;
    var len = c.length;
    delayValue = Number(c.substr(pos,(len-pos)));
    $('#header4').html(results[4+fileOffset]);
    for (i=(5+fileOffset); i<results.length;i++) {
      $('.datapoints').append(results[i]+"<br>");
      c = results[i];
      //  Extract Time and Date information by parsing the string.  Format is: 06/15/14 19:30:59 UTC
      // datapoints[i-5-fileOffset] = new Date(c.substr(0,6)+"20"+c.substr(6,2)+" "+c.substr(9,8)+" UTC");
      datapoints[i-5-fileOffset] = new Date(c + tz);
    }
  }
  results = [];  // Clear the array as we are now done with it.
}
// Call to draw the table once Google visualization is loaded
function drawTable() {
  // Refine Table Options
  var options = {title:'Total Counts by Daypart by Day',
     width : 600,
     showRowNumber: true};
  // Report Table Options
  var options2 = {'title':'Total Counts by Daypart by Day',
     'width':600};
 // If we have already retrieved weather data, make sure it is reapplied to the table
 if (weatherData.length) {
   for (n=0; n<daysCovered.length; n++) {
     data.setFormattedValue(n,6,weatherData[n]);
   }
 }
 table.draw(data,options);
 table2.draw(data,options2);
}
// Call to draw the chart once Google visualization is loaded
function drawChart() {
  var options = {
    title: 'Events by Day and Daypart',
    width: 700,
    height: 400,
    legend: { position: 'side', maxLines: 3, textStyle: {color: 'blue', fontSize: 10, } },
    bar: { groupWidth: '75%' },
    hAxis: {
          title: 'Date',
          format: 'mm/dd',
          viewWindow: {
            min: [7, 30, 0],
            max: [17, 30, 0]
          }},
    isStacked: true,
  };
 chart.draw(chartdata, options);
}
//Function to format a date string to match WeatherBug's Requirements
function formatDate() {
  var currentDay = 0;
  for (i = 0; i < datapoints.length; i++) { 
    var loopDay = datapoints[i].getDate();
    if (loopDay != currentDay) {
      var tempString = "";
      daysCovered[daysCoveredIndex] = datapoints[i].getFullYear().toString();
      if (datapoints[i].getMonth() <10) {
        tempString = "0";
      }
      daysCovered[daysCoveredIndex] += tempString + (datapoints[i].getMonth() + 1).toString();
      if (datapoints[i].getDate() < 10) {
        tempString = "0";
      }
      else {
        tempString = "";
      }
      daysCovered[daysCoveredIndex] += tempString + datapoints[i].getDate().toString();
      daysCoveredIndex++;
      currentDay = datapoints[i].getDate();
    }
  }
  console.log(daysCovered);  // Debug line for daysCovered array
}
//This function will apply filtering to the datapoints array and create the filteredDatapoints array
function filterArray(delta, doubleDelta) {
  var current;
  var next;
  var fi = 0;
  filteredDatapoints = [];  // clear and build anew
  if (delta) {              // Moderate Filter (delta,0)
    for (i=0; i < datapoints.length; i++) {
      filteredDatapoints[fi] = datapoints[i];
      current = datapoints[i];
      next = datapoints[i+1];
      if (next-current <= delta) {
        i++;
      }
      fi++;
    }
  }
  else {
    var runningTotal = 0;
    var n = 1;
    for (i=0; i < datapoints.length; i++) {
      filteredDatapoints[fi] = datapoints[i];
      current = datapoints[i];
      next = datapoints[i+1];
      runningTotal += next - current;
      while (runningTotal/n <= doubleDelta ) {  // compare the average delta to the doubleDelta
        n++; // for computing the average delta
        i++;  // running average is less than the doubleDelta - in the while loop skipping data points
        current = datapoints[i];
        next = datapoints[i+1];
        runningTotal += next - current;  // Keeps a running total of the deltas
      }
      n = 1;
      fi++;
      runningTotal = 0;  // reset the running average and keep plowing through the datapoints array
    }
  }
}
// Here is where we will populate the table for the Refine and Report tab
function populateTable(array) {  
  var currentDay, currentDateString, currentDate, currentHour;
  var rowSum = 0;
  var tableSum = 0;
  var morningSum = 0;
  var afternoonSum = 0;
  var eveningSum = 0;
  var nightSum = 0;
  var morning = 0;
  var afternoon = 0;
  var evening = 0;
  var night = 0;  
  currentDateTime(array[0]);
  // We will now start stepping through the array and summing for each unique day
  for (i = 0; i < array.length; i++) {
    var loopDay = array[i].getDate();
    if (loopDay === currentDay) {
      currentHour = array[i].getHours();
      evalTime(currentHour);
    }
    else {
      // Here because it is a new day.  Close out the old
      rowSum = morning + afternoon + evening + night;
      tableSum += rowSum;
      data.addRows([[currentDateString, morning, afternoon, evening, night,rowSum,""]]);
      chartdata.addRows([[currentDate,morning,afternoon,evening,night]]);
       // And start the new
      morningSum += morning;
      afternoonSum += afternoon;
      eveningSum += evening;
      nightSum += night; 
      morning = afternoon = evening = night = rowSum= 0; 
      currentDateTime(array[i]);
      evalTime(currentHour);
    }
  }
  rowSum = morning + afternoon + evening + night;
  tableSum += rowSum;
  data.addRows([[currentDateString, morning, afternoon, evening, night, rowSum,""]]);
  data.addRows([["Totals", morningSum, afternoonSum, eveningSum, nightSum, tableSum,""]]);
  chartdata.addRows([[currentDate,morning,afternoon,evening,night]]);
  // Takes the current row and populates the date and time variables
  function currentDateTime(currentRow) {
    currentDay = currentRow.getDate();
    currentDateString = currentRow.toDateString();
    currentDate = (currentRow.getMonth()+1).toString() + "/" + currentDay.toString();
    currentHour = currentRow.getHours();
  }
  //Takes the current time and assigns the counts to the right rows
  function evalTime(time) {
    if (time >= 6 && time <12)  morning++; 
    if (time >= 12 && time < 18) afternoon++;
    if (time >= 18 && time < 22) evening++;
    else if (time >= 22 || time < 6) night++;   
  }
}
//Event Handler for the Refine Tab
$('#tabs a[href="#refine"]').click('shown', function (e) {
  if (!data.getNumberOfRows()) {
    // We will now trim the data points based on the values from the Preview tab
    datapoints.splice(-$('#bottomDrop').val(),$('#bottomDrop').val());
    datapoints.splice(0,$('#topDrop').val());
    // Now we will create the summary data for the Refine Tab
    $('#startTime').html("This session stated on " + datapoints[0]);
    $('#endTime').html("This session ended on " + datapoints[datapoints.length-1]);
    $('#reportSubtitle').html("Final Report for data collection between " + datapoints[0].toLocaleDateString() + " and " + datapoints[datapoints.length-1].toLocaleDateString());
    if (!daysCovered.length) formatDate();
    populateTable(datapoints);
    drawTable();
    drawChart();
    $('#weatherButton').on('click', function () {
      for (n=0; n < daysCovered.length; n++) {
        getWeather(n);
        if (n === 9) break;   // For the free WeatherUnderground API, you can only get 10 calls a minute
      }
    });
    $('#noFilter').on('click', function () {
      // No filter - just the raw data
      data.removeRows(0,data.getNumberOfRows());
      chartdata.removeRows(0,chartdata.getNumberOfRows());
      populateTable(datapoints);
      drawTable();
      drawChart();
    });
    $('#modFilter').on('click', function () {
      //This filter just looks at the difference between two datapoints and filters if it is less than twice the delay value
      filterArray(2*delayValue,0);
      data.removeRows(0,data.getNumberOfRows());
      chartdata.removeRows(0,chartdata.getNumberOfRows());
      populateTable(filteredDatapoints);
      drawTable();
      drawChart();
    });
    $('#highFilter').on('click', function () {
      filterArray(0,2*delayValue);
      data.removeRows(0,data.getNumberOfRows());
      chartdata.removeRows(0,chartdata.getNumberOfRows());
      populateTable(filteredDatapoints);
      drawTable();
      drawChart();
    });
  }
});
// JSON calls to WeatherUnderground's API
var getWeather = function(day) {
  $.ajax({
      url : url + "history_" + daysCovered[day] + "/q/" + $('#stInput').val() + "/" + $('#cityInput').val() + ".json",
      dataType : "jsonp",
      success : function(parsed_json) {
        var meantemp = parsed_json.history.dailysummary[0].meantempi;
        var rainfall = parsed_json.history.dailysummary[0].rain;
        weatherData[day] = meantemp + "F Avg / " + rainfall +"in. rain";
        drawTable();
      }
  });
};
// Where the first interface listeners are and where we hide distractions until the user presses "start"
var main = function () {
  $('#tabs').tab();  // Event handler for tabs
  // Event Handler for the file browse button
  $(document).on('change', '.btn-file :file', function() {
    var input = $(this),
    numFiles = input.get(0).files ? input.get(0).files.length : 1,
    label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
    input.trigger('fileselect', [numFiles, label]);
  });
  // Event Handler for the "Start" button
  $('.btn-file :file').on('fileselect', function(event, numFiles, label) {      
     var input = $(this).parents('.input-group').find(':text'),
     log = numFiles > 1 ? numFiles + ' files selected' : label; 
     if( input.length ) {
       input.val(log);
     } 
     else {
       if( log ) alert(log);
     }
   });
  // The idea here is to hide everything until they click "start"
  $('h4').hide();
  $(".form-inline, .form, .form-buttons, .drop-dialog").hide();
  $('#table_div, #chart_div,#table2_div').hide();
  // Set a callback to run when the Google Visualization API is loaded.
  google.setOnLoadCallback(drawTable);  
  google.setOnLoadCallback(drawChart);
};
// After the page loads, we start with main
$(document).ready(main);
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
chipmcpro
0viewers