Difference between revisions of "Widget:WFSPCompare"

From Open Energy Information

(upgrades to viz)
(color change for green buttons)
 
(35 intermediate revisions by 4 users not shown)
Line 6: Line 6:
 
</pre>
 
</pre>
 
[[Category:Widgets]]
 
[[Category:Widgets]]
[[Category:WindForSchools]]
+
[[Category:Wind for Schools]]
 
</noinclude><includeonly>
 
</noinclude><includeonly>
  
Line 78: Line 78:
 
g.button text.buttonText {
 
g.button text.buttonText {
 
   font-family: Oxygen;
 
   font-family: Oxygen;
 +
  fill: #FFFFFF;
 +
}
 +
 +
td.not-reporting {
 +
  background: #eee;
 +
  color: #888;
 
}
 
}
  
Line 100: Line 106:
 
}
 
}
  
 +
#wfspCompareDownload .modal-header,
 
#wfspCustomRange .modal-header {
 
#wfspCustomRange .modal-header {
 
   color: #fff;
 
   color: #fff;
Line 112: Line 119:
 
}
 
}
  
 +
.datepicker.dropdown-menu {
 +
  z-index: 1980 !important;
 +
}
  
 +
.date .form-control[readonly] {
 +
  background: none;
 +
}
  
 
</style>
 
</style>
 
+
<!--load bootstrap datepicker-->
 
+
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/css/datepicker.css" rel="stylesheet" type="text/css" />
<!-- <link rel="stylesheet" type="text/css" href="/w/skins/OpenEI/resources/air-datepicker/css/datepicker.min.css">
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/js/bootstrap-datepicker.js"></script>
<script type="text/javascript" src="/w/skins/OpenEI/resources/air-datepicker/js/datepicker.min.js"></script>
 
<script type="text/javascript" src="/w/skins/OpenEI/resources/air-datepicker/js/i18n/datepicker.en.js"></script>
 
 
 
<div>
 
  <input id="MaxDatepicker" type="text"
 
  multiple-dates-separator: " - ">
 
</div> -->
 
 
 
<!-- <input id="MaxDatepicker" type="text"> -->
 
<script>
 
  // $('#MaxDatepicker').datepicker({
 
  //    range: "true"
 
  //    language: "en"
 
  //    class: "datepicker-here"/>
 
  //    language: 'en',
 
  //    maxDate: new Date() // Now can select only dates up until today
 
  // });
 
</script>
 
 
 
 
 
  
 
<!-- Modal -->
 
<!-- Modal -->
Line 149: Line 142:
 
       <div class="modal-body">
 
       <div class="modal-body">
 
         <form id="wfspCustomRangeForm" class="input-group">
 
         <form id="wfspCustomRangeForm" class="input-group">
           <div class="form-group">
+
           <label>Start Date: </label>
            <label for="customBeginDate">Start Date</label>
+
          <div id="startDate" class="input-group date">
            <input type="date" class="form-control" id="customBeginDate" name="begin-date">
+
            <input class="form-control" type="text" id="customBeginDate" name="begin-date" readonly="true"/>
 +
            <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
 
           </div>
 
           </div>
           <div class="form-group">
+
           <label>End Date: </label>
            <label for="customEndDate">End Date</label>
+
          <div id="endDate" class="input-group date">
            <input type="date" class="form-control" id="customEndDate" name="end-date">
+
            <input class="form-control" type="text" id="customEndDate" name="end-date" readonly="true"/>
 +
            <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
 
           </div>
 
           </div>
 
         </form>
 
         </form>
Line 164: Line 159:
 
           <div type="button" class="btn btn-default" data-dismiss="modal">Close</div>
 
           <div type="button" class="btn btn-default" data-dismiss="modal">Close</div>
 
         </div>
 
         </div>
 +
      </div>
 +
    </div>
 +
  </div>
 +
</div>
 +
 +
<!-- Download Modal -->
 +
<div class="modal fade" id="wfspCompareDownload" role="dialog">
 +
  <div class="modal-dialog">
 +
    <div class="modal-content">
 +
      <div class="modal-header">
 +
        <button type="button" class="close" data-dismiss="modal">&times;</button>
 +
        <h3 class="modal-title">Download Data</h3>
 +
      </div>
 +
      <div class="modal-body text-center">
 +
        <p class="h4">Date Range: <span id="downloadLinksRange">All Dates</span></p>
 +
        <div id="downloadLinks" class="text-center"></div>
 +
        <div id="downloadLinksLoading"><i class="fa fa-spinner fa-spin" aria-hidden="true"></i><br>Loading...</div>
 +
      </div>
 +
      <div class="modal-footer">
 +
        <div type="button" class="btn btn-default" data-dismiss="modal">Close</div>
 
       </div>
 
       </div>
 
     </div>
 
     </div>
Line 182: Line 197:
 
   </div>
 
   </div>
 
</div>
 
</div>
 
  
 
<!-- Preset Buttons -->
 
<!-- Preset Buttons -->
<div id="div_preset_btns" style="overflow: scroll; display: none">
+
<div id="div_preset_btns" class="col-xs-12 center hidden" style="overflow: scroll;">
 +
  <svg id="svg_download_btn" width="165" height="50"></svg>
 
   <svg id="svg_preset_btns" width="700" height="50"></svg>
 
   <svg id="svg_preset_btns" width="700" height="50"></svg>
 
</div>
 
</div>
Line 191: Line 206:
  
 
<!-- Table -->
 
<!-- Table -->
<div id="div_table" style="overflow: scroll; display: none">
+
<div id="div_table" class="col-xs-12 center hidden" style="overflow: scroll;">
 
</div>
 
</div>
  
Line 200: Line 215:
  
  
 
+
<script>
 
+
$(document).ready(function(){
 +
  //bootstrap datepicker
 +
  $("#startDate, #endDate").datepicker({
 +
    autoclose: true,
 +
    todayHighlight: true,
 +
    todayBtn: true,
 +
    format: 'yyyy-mm-dd',
 +
    endDate: '+0d',
 +
    zIndexOffset: '1980'
 +
  });
 +
  $('#startDate').datepicker('update');
 +
  $('#endDate').datepicker('update', new Date());
 +
});
 +
</script>
  
 
<script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script>
 
<script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script>
Line 272: Line 300:
 
   var schools_raw = json_schools["query"]["results"];
 
   var schools_raw = json_schools["query"]["results"];
 
   var schools = [];
 
   var schools = [];
 +
  var groupedSchools = {};
  
 
   for (var key in schools_raw) {
 
   for (var key in schools_raw) {
Line 281: Line 310:
 
       //if (available_turbineIDs.includes(turbine_id)) {
 
       //if (available_turbineIDs.includes(turbine_id)) {
 
       if (available_turbineIDs.indexOf(turbine_id) >= 0) {
 
       if (available_turbineIDs.indexOf(turbine_id) >= 0) {
         schools.push(  
+
         schools.push({
           {
+
           "turbineID": turbine_id,
            "turbineID": turbine_id,
+
          "school_name": school_name,
            "school_name": school_name,
+
          "state": state,
            "state": state,
+
          "state_school_name": (state + " - " + school_name),
            "state_school_name": (state + " - " + school_name),
+
          "school_name_state": (school_name + " - " + state)
            "school_name_state": (school_name + " - " + state)
+
        });
          });
 
 
       }
 
       }
 
     }
 
     }
 
   }
 
   }
  
   // Sort Schools by State  
+
   // Sort Schools by State
 
   schools.sort(function(a, b) {
 
   schools.sort(function(a, b) {
 
       var textA = a.state_school_name.toUpperCase();
 
       var textA = a.state_school_name.toUpperCase();
Line 300: Line 328:
 
   });
 
   });
  
   schools.unshift(  
+
   schools.unshift(
     {  
+
     {
 
       "turbineID": "n/a",
 
       "turbineID": "n/a",
 
       "school_name": "n/a",
 
       "school_name": "n/a",
Line 310: Line 338:
  
 
   $.each(schools, function(i, option) {
 
   $.each(schools, function(i, option) {
       $('#sel').append($('<option/>').attr("value", option.turbineID).text(option.school_name_state));
+
    if (option.turbineID != 'n/a') {
 +
      if (!groupedSchools[option.state]) { groupedSchools[option.state] = []; }
 +
      groupedSchools[option.state].push({
 +
        "turbineID": option.turbineID,
 +
        "school_name": option.school_name,
 +
        "state": option.state,
 +
        "state_school_name": option.state_school_name,
 +
        "school_name_state": option.school_name_state,
 +
       });
 +
    }
 +
  });
 +
 
 +
  $('#sel').append('<option disabled selected value> -- Select a School to Compare -- </option>');
 +
  $.each(groupedSchools, function(stateName, schoolList) {
 +
    var optionGroup = '<optgroup label="' + stateName + '">';
 +
    $.each(schoolList, function(i, option) {
 +
      optionGroup += '<option value="' + option.turbineID + '">' + option.school_name_state + '</option>';
 +
    });
 +
    optionGroup += '</optgroup>';
 +
    $('#sel').append(optionGroup);
 
   });
 
   });
  
Line 333: Line 380:
 
   var tbody = table.append('tbody');
 
   var tbody = table.append('tbody');
 
   var columns = (function () {if ($(window).width()>50) {
 
   var columns = (function () {if ($(window).width()>50) {
       return ['ID', 'School Name','Location','Power (kW)','Wind (m/s)','Energy Today (kWh)','Total Energy (kWh)','Turbine Status','System Status','Last Reported'];
+
       return ['ID', 'School Name','Location','Power (W)','Wind (m/s)','Energy Today (kWh)','Total Energy (kWh)','Turbine Status','System Status','Last Reported'];
 
     } else {
 
     } else {
 
       return ['ID', 'School Name','Energy Today (kWh)','Total Energy (kWh)','System Status']
 
       return ['ID', 'School Name','Energy Today (kWh)','Total Energy (kWh)','System Status']
 
     }} )();
 
     }} )();
 
+
 
  
 
   function tabulate(data,columns) {
 
   function tabulate(data,columns) {
Line 358: Line 405:
 
         .enter()
 
         .enter()
 
       .append('tr');
 
       .append('tr');
      
+
 
 +
 
 +
     // Number of days since last report to be considered active.
 +
    var daysSinceLastViableReport = 3;
 +
    var lastViableReportTime = new Date();
  
 
     var cells = rows.selectAll('td')
 
     var cells = rows.selectAll('td')
 
         .data(function(row) {
 
         .data(function(row) {
 +
          lastViableReportTime.setDate(lastViableReportTime.getDate() - daysSinceLastViableReport);
 +
          var lastReported = new Date((row['Last Reported']).concat(" UTC").replace(/-/g, "/"));
 +
          if (lastReported < lastViableReportTime) {
 +
            row['System Status'] = 'Not reporting';
 +
          }
 +
 
           return columns.map(function (column) {
 
           return columns.map(function (column) {
 
             return { column: column, value: row[column] }
 
             return { column: column, value: row[column] }
Line 368: Line 425:
 
         .enter()
 
         .enter()
 
       .append('td')
 
       .append('td')
         .text(function (d) {  
+
         .text(function (d) {
           if ( (d.column != "ID") && (d.column != "Last Reported") ) {  
+
           if ( (d.column != "ID") && (d.column != "Last Reported") ) {
             if (typeof d.value === 'string' || d.value instanceof String) { return d.value }  
+
             if (typeof d.value === 'string' || d.value instanceof String) { return d.value }
 
             else { return f(d.value) }
 
             else { return f(d.value) }
 
           }
 
           }
Line 379: Line 436:
 
         })
 
         })
 
         .attr("class", function(d) {
 
         .attr("class", function(d) {
             if (d.value == "Running") {return "alert-success"}  
+
             if (d.value == "Running") {return "alert-success"}
 
               else if (d.value == "Not Running") {return "alert-danger"}
 
               else if (d.value == "Not Running") {return "alert-danger"}
                 else if (d.column == "System Status") {return "alert-warning"}  } )
+
                 else if (d.value == "Not reporting") {return "not-reporting"}
 +
                  else if (d.column == "System Status") {return "alert-warning"}  } )
 
         .attr("bgcolor", function(d) {
 
         .attr("bgcolor", function(d) {
 
             if (d.column == "ID") {return chart_colors[turbineIDs_selected.indexOf(d.value)]} } )
 
             if (d.column == "ID") {return chart_colors[turbineIDs_selected.indexOf(d.value)]} } )
Line 387: Line 445:
 
     cells.exit().remove();
 
     cells.exit().remove();
  
     buttons = rows.selectAll("td.button")
+
     buttons = rows.selectAll("td.button")
 
               .data(function(d) {return [d];})
 
               .data(function(d) {return [d];})
 
               .enter()
 
               .enter()
Line 394: Line 452:
 
                 .append("button")
 
                 .append("button")
 
                 .html('<i class="fa fa-trash" aria-hidden="true"></i>')
 
                 .html('<i class="fa fa-trash" aria-hidden="true"></i>')
                 .on("click", function(d){  
+
                 .on("click", function(d){
 
                   var drop_index = turbineIDs_selected.indexOf(d.ID);
 
                   var drop_index = turbineIDs_selected.indexOf(d.ID);
 
                   if (drop_index > -1) {
 
                   if (drop_index > -1) {
Line 403: Line 461:
 
     buttons.exit().remove();
 
     buttons.exit().remove();
 
     rows.exit().remove();
 
     rows.exit().remove();
     var x = document.getElementById('div_table');
+
     //var x = document.getElementById('div_table');
     x.style.display = 'block';
+
     //x.style.display = 'block';
 +
    $('#div_table').removeClass('hidden');
 
     return table;
 
     return table;
 
   }
 
   }
Line 410: Line 469:
  
 
   var chart_colors = [
 
   var chart_colors = [
     "#1976D2", "#FFC107", "#009688", "#7B1FA2",  
+
     "#1976D2", "#FFC107", "#009688", "#7B1FA2",
     "#00E5FF", "#EEFF41", "#1DE9B6", "#D500F9",  
+
     "#00E5FF", "#EEFF41", "#1DE9B6", "#D500F9",
     "#82B1FF", "#FFFF8D", "#64FFDA", "#EA80FC",  
+
     "#82B1FF", "#FFFF8D", "#64FFDA", "#EA80FC",
 
     "#0D47A1", "#C89924", "#004D40", "#C51162"
 
     "#0D47A1", "#C89924", "#004D40", "#C51162"
 
   ];
 
   ];
Line 422: Line 481:
 
     var turbineID_selected = e.options[e.selectedIndex].value;
 
     var turbineID_selected = e.options[e.selectedIndex].value;
 
     //if ( (turbineID_selected != "n/a") && !turbineIDs_selected.includes(turbineID_selected) ) {
 
     //if ( (turbineID_selected != "n/a") && !turbineIDs_selected.includes(turbineID_selected) ) {
     if ( (turbineID_selected != "n/a") && !turbineIDs_selected.indexOf(turbineID_selected) >= 0 ) {
+
     if (turbineID_selected && (turbineID_selected != "n/a") && !turbineIDs_selected.indexOf(turbineID_selected) >= 0 ) {
       turbineIDs_selected.push(turbineID_selected)
+
       turbineIDs_selected.push(turbineID_selected);
 
     }
 
     }
 
     if (turbineID_init != "NULL") {
 
     if (turbineID_init != "NULL") {
       //if (available_turbineIDs.includes(turbineID_init)) {  
+
       //if (available_turbineIDs.includes(turbineID_init)) {
       if (available_turbineIDs.indexOf(turbineID_init) >= 0) {  
+
       if (available_turbineIDs.indexOf(turbineID_init) >= 0) {
 
         turbineIDs_selected.push(turbineID_init);
 
         turbineIDs_selected.push(turbineID_init);
 
         turbineID_init = "NULL";
 
         turbineID_init = "NULL";
Line 434: Line 493:
 
     console.log(turbineIDs_selected);
 
     console.log(turbineIDs_selected);
  
     $('#sel').empty();
+
     $('#sel').empty().append('<option disabled selected value> -- Select a School to Compare -- </option>');
     $.each(schools, function(i, option) {
+
     $.each(groupedSchools, function(stateName, schoolList) {
        //if ( !turbineIDs_selected.includes(option.turbineID) ) {  
+
      var optionGroup = '<optgroup label="' + stateName + '">';
         if ( !turbineIDs_selected.indexOf(option.turbineID) >= 0) {
+
      $.each(schoolList, function(i, option) {
          $('#sel').append($('<option/>').attr("value", option.turbineID).text(option.school_name_state));
+
         optionGroup += '<option value="' + option.turbineID + '">' + option.school_name_state + '</option>';
        }
+
      });
 +
      optionGroup += '</optgroup>';
 +
      $('#sel').append(optionGroup);
 
     });
 
     });
  
Line 454: Line 515:
 
     }
 
     }
  
   
+
 
 
     function ajax_loop(idx) {
 
     function ajax_loop(idx) {
 
     // while (idx < num_turbineIDs) {
 
     // while (idx < num_turbineIDs) {
Line 493: Line 554:
 
               "School Name": metadata[0]["school_name"],
 
               "School Name": metadata[0]["school_name"],
 
               "Location": metadata[0]["state"],
 
               "Location": metadata[0]["state"],
               "Power (kW)": summary_attributes["power"],
+
               "Power (W)": summary_attributes["power"],
 
               "Wind (m/s)": summary_attributes["wind"],
 
               "Wind (m/s)": summary_attributes["wind"],
 
               "Energy Today (kWh)": summary_attributes["energy_today"],
 
               "Energy Today (kWh)": summary_attributes["energy_today"],
Line 504: Line 565:
 
       }
 
       }
 
     }
 
     }
   
+
 
  
 
     function table_element_build() {
 
     function table_element_build() {
Line 511: Line 572:
 
         header = false;
 
         header = false;
 
         tabulate(table_data,columns);
 
         tabulate(table_data,columns);
       } else {  
+
       } else {
 
         header = true;
 
         header = true;
 
         tabulate(table_data,columns) }
 
         tabulate(table_data,columns) }
 
       $('select').each(function() { this.selectedIndex = 0 }); // Reset Default Drop-Down Text
 
       $('select').each(function() { this.selectedIndex = 0 }); // Reset Default Drop-Down Text
     
+
 
 
       if ( (turbineID_selected != "n/a") || (btn == "drop") || (btn == "initialize") ) {
 
       if ( (turbineID_selected != "n/a") || (btn == "drop") || (btn == "initialize") ) {
 
         if (table_data.length > 0) {
 
         if (table_data.length > 0) {
Line 534: Line 595:
 
           context.selectAll("text").remove();
 
           context.selectAll("text").remove();
 
           svg.selectAll(".zoom").remove();
 
           svg.selectAll(".zoom").remove();
 +
          svg_download.selectAll("g").remove();
 
           svg2.selectAll("g").remove();
 
           svg2.selectAll("g").remove();
 
           var x = document.getElementById('div_graphs');
 
           var x = document.getElementById('div_graphs');
 
           x.style.display = 'none';
 
           x.style.display = 'none';
           var x = document.getElementById('div_preset_btns');
+
           //var x = document.getElementById('div_preset_btns');
           x.style.display = 'none';
+
           //x.style.display = 'none';
 +
          $('#div_preset_btns').addClass('hidden');
 
         }
 
         }
 
       }
 
       }
Line 552: Line 615:
  
 
   var svg = d3.select("#svg_graphs"),
 
   var svg = d3.select("#svg_graphs"),
 +
      svg_download = d3.select("#svg_download_btn"),
 
       svg2 = d3.select("#svg_preset_btns"),
 
       svg2 = d3.select("#svg_preset_btns"),
 
       svg_width = parseInt( 0.9 * $(window).width() ),
 
       svg_width = parseInt( 0.9 * $(window).width() ),
Line 564: Line 628:
 
       margin_focus1 = {top: parseInt(svg_height * 0.175), right: parseInt(svg_width * 0.01), bottom: parseInt(svg_height * 0.5), left: parseInt(svg_width * 0.1) },
 
       margin_focus1 = {top: parseInt(svg_height * 0.175), right: parseInt(svg_width * 0.01), bottom: parseInt(svg_height * 0.5), left: parseInt(svg_width * 0.1) },
 
       margin_focus2 = {top: parseInt(svg_height * 0.575), right: parseInt(svg_width * 0.01), bottom: parseInt(svg_height * 0.05), left: parseInt(svg_width * 0.1) },
 
       margin_focus2 = {top: parseInt(svg_height * 0.575), right: parseInt(svg_width * 0.01), bottom: parseInt(svg_height * 0.05), left: parseInt(svg_width * 0.1) },
 
+
 
 
       width_focus = svg_width - margin_focus1.left - margin_focus1.right,
 
       width_focus = svg_width - margin_focus1.left - margin_focus1.right,
 
       height_focus = svg_height - margin_focus1.top - margin_focus1.bottom,
 
       height_focus = svg_height - margin_focus1.top - margin_focus1.bottom,
Line 603: Line 667:
 
       .y0(height_context)
 
       .y0(height_context)
 
       .y1(function(d) { return yScale_context(d.powerOutput); });
 
       .y1(function(d) { return yScale_context(d.powerOutput); });
 
 
  
 
   var focus1 = svg.append("g")
 
   var focus1 = svg.append("g")
Line 641: Line 703:
 
     context.selectAll("text").remove();
 
     context.selectAll("text").remove();
 
     svg.selectAll(".zoom").remove();
 
     svg.selectAll(".zoom").remove();
 +
    svg_download.selectAll("g").remove();
 
     svg2.selectAll("g").remove();
 
     svg2.selectAll("g").remove();
  
 
     var x = document.getElementById('div_graphs');
 
     var x = document.getElementById('div_graphs');
 
     x.style.display = 'block';
 
     x.style.display = 'block';
     var x = document.getElementById('div_preset_btns');
+
     //var x = document.getElementById('div_preset_btns');
     x.style.display = 'block';
+
     //x.style.display = 'block';
 +
    $('#div_preset_btns').removeClass('hidden');
  
  
Line 708: Line 772:
 
         .attr('height', height_context);
 
         .attr('height', height_context);
  
     
+
 
 
       for (var i = 0; i < num_turbineIDs; i++) {
 
       for (var i = 0; i < num_turbineIDs; i++) {
 
         Turbine_ID = turbineIDs_selected[i];
 
         Turbine_ID = turbineIDs_selected[i];
Line 714: Line 778:
  
 
         focus1.append("path")
 
         focus1.append("path")
             .datum(data.filter(function(d){ return ( d.turbineID == Turbine_ID );} ))  
+
             .datum(data.filter(function(d){ return ( d.turbineID == Turbine_ID );} ))
 
             .attr("class", "area area"+(i+1))
 
             .attr("class", "area area"+(i+1))
 
             .attr("d", area_focus1)
 
             .attr("d", area_focus1)
 
             .style("stroke", series_color);
 
             .style("stroke", series_color);
       }  
+
       }
  
 
       focus1.append("g")
 
       focus1.append("g")
Line 822: Line 886:
  
 
       context.append("path")  // append unselected context data as white lines
 
       context.append("path")  // append unselected context data as white lines
           .datum(data)  
+
           .datum(data)
 
           .attr("class", "area_context_unselected")
 
           .attr("class", "area_context_unselected")
 
           .attr("d", area_context)
 
           .attr("d", area_context)
Line 831: Line 895:
 
         series_color = chart_colors[i];
 
         series_color = chart_colors[i];
 
         context.append("path")
 
         context.append("path")
             .datum(data.filter(function(d){ return ( d.turbineID == Turbine_ID );} ))  
+
             .datum(data.filter(function(d){ return ( d.turbineID == Turbine_ID );} ))
 
             .attr("class", "area_context area"+(i+1))
 
             .attr("class", "area_context area"+(i+1))
 
             .attr("d", area_context)
 
             .attr("d", area_context)
Line 876: Line 940:
  
  
 +
      // var defaultColor= "#12f494";
 +
      // var hoverColor= "#2BDA82";
 +
      // var pressedColor= "#12f494";
 +
      var defaultColor= "#3ac093";
 +
      var hoverColor= "#30a07b";
 +
      var pressedColor= "#3ac093";
 +
      var bWidth= 105; //button width
 +
      var bHeight= 35; //button height
 +
      var bSpace= 10; //space between buttons
 +
      var x0= 10; //x offset
 +
      var y0= 5; //y offset
 +
 +
      // Download button
 +
      var downloadButton = svg_download.append("g").attr("id", "downloadBtn");
 +
 +
      var downloadButtonGroup= downloadButton.selectAll("g.button")
 +
                            .data(['Download Data'])
 +
                            .enter()
 +
                            .append("g")
 +
                            .attr("class","button")
 +
                            .attr("data-toggle", "modal")
 +
                            .attr("data-target", "#wfspCompareDownload")
 +
                            .style("cursor","pointer")
 +
                            .on("click",function(d,i) {
 +
                              // Download modal update.
 +
                              $('#downloadLinksLoading').removeClass('hidden');
 +
                              $('#downloadLinks').empty().addClass('hidden');
 +
 +
                              var s = d3.event.selection || xScale_focus1.range();
 +
                              var formatMonth = d3.timeFormat("%m");
 +
                              var formatYear = d3.timeFormat("%Y");
 +
                              var minDate = formatYear(xScale_focus1.invert(s[0])) + formatMonth(xScale_focus1.invert(s[0]));
 +
                              var maxDate = formatYear(xScale_focus1.invert(s[1])) + formatMonth(xScale_focus1.invert(s[1]));
 +
                              base_url = "/services/api/3/WFS/?turbine_id="
 +
 +
                              function ajax_loop_download(idx) {
 +
                                var Turbine_ID = turbineIDs_selected[idx];
 +
                                var turbine_url = base_url + Turbine_ID
 +
                                $.ajax({
 +
                                  'url': turbine_url,
 +
                                  cache: false,
 +
                                  dataType: 'json',
 +
                                  success: function (available_months) {
 +
                                      for (var k = 0; k < available_months.length; k++) {
 +
                                        if ( (available_months[k] >= minDate) && (available_months[k] <= maxDate)) {
 +
                                          turbine_url = turbine_url.concat("&months[]=");
 +
                                          turbine_url = turbine_url.concat(available_months[k]);
 +
                                        };
 +
                                      };
 +
                                      turbine_url = turbine_url.concat("&format=10min");
 +
                                      // Get school name.
 +
                                      var schoolName = 'Download';
 +
                                      for (var i in schools) {
 +
                                        if (schools[i].turbineID == Turbine_ID) {
 +
                                          schoolName = schools[i].school_name;
 +
                                          break;
 +
                                        }
 +
                                      }
 +
                                      $('#downloadLinks').append('<p><a href="' + turbine_url + '" target="_blank" class="btn btn-wfsp-secondary"><i class="fa fa-cloud-download" aria-hidden="true"></i> ' + schoolName + '</a></p>');
 +
                                      idx += 1;
 +
                                      if (idx < num_turbineIDs) {
 +
                                        ajax_loop_download(idx);
 +
                                      } else {
 +
                                        $('#downloadLinksLoading').addClass('hidden');
 +
                                        $('#downloadLinks').removeClass('hidden');
 +
                                      }
 +
                                  },
 +
                                  fail: function (jqXHR, textStatus, errorThrown) {
 +
                                    $element.html(errorHTML);
 +
                                  }
 +
                                });
 +
                              };
 +
                              var idx = 0;
 +
                              ajax_loop_download(idx);
 +
                              // End download modal update.
 +
                            })
 +
                            .on("mouseover", function() {
 +
                                    d3.select(this)
 +
                                        .select("rect")
 +
                                        .attr("fill",hoverColor);
 +
                            })
 +
                            .on("mouseout", function() {
 +
                                    d3.select(this)
 +
                                        .select("rect")
 +
                                        .attr("fill",defaultColor);
 +
                            });
 +
 +
      downloadButtonGroup.append("rect")
 +
                  .attr("class","buttonRect")
 +
                  .attr("width",145)
 +
                  .attr("height",35)
 +
                  .attr("x",function(d,i) {return x0+(bWidth+bSpace)*i;})
 +
                  .attr("y",y0)
 +
                  .attr("rx",3) //rx and ry give the buttons rounded corners
 +
                  .attr("ry",3)
 +
                  .attr("fill",defaultColor);
 +
 +
      downloadButtonGroup.append("text")
 +
                  .attr("class","download-btn-text")
 +
                  .attr("x",82.5)
 +
                  .attr("y", 22.5)
 +
                  .attr("text-anchor","middle")
 +
                  .attr("dominant-baseline","central")
 +
                  .attr("fill","white")
 +
                  .text('');
 +
 +
      var downloadBtnText = downloadButtonGroup.select(".download-btn-text");
 +
      downloadBtnText.append('tspan')
 +
                  .attr("font-family","FontAwesome")
 +
                  .text('\uf0ed');
 +
      downloadBtnText.append('tspan')
 +
                  .attr("font-family","Oxygen")
 +
                  .text(' Download Data');
  
 
       // Timeline Buttons
 
       // Timeline Buttons
Line 882: Line 1,059:
  
 
       var labels= ['Today','Last 7 Days','Last 30 Days','Last Year','Custom Range','Reset'];
 
       var labels= ['Today','Last 7 Days','Last 30 Days','Last Year','Custom Range','Reset'];
 
      var defaultColor= "#303f9f";
 
      var hoverColor= "#001980";
 
      var pressedColor= "#303f9f";
 
  
 
       var buttonGroups= allButtons.selectAll("g.button")
 
       var buttonGroups= allButtons.selectAll("g.button")
Line 905: Line 1,078:
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .translate(-s[0], 0));
 
                                     .translate(-s[0], 0));
 +
                                    $('#downloadLinksRange').html(d);
 
                                 } else if (i == 1) {
 
                                 } else if (i == 1) {
 
                                     var t_svg = svg.transition()
 
                                     var t_svg = svg.transition()
Line 913: Line 1,087:
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .translate(-s[0], 0));
 
                                     .translate(-s[0], 0));
 +
                                    $('#downloadLinksRange').html(d);
 
                                 } else if (i == 2) {
 
                                 } else if (i == 2) {
 
                                     var t_svg = svg.transition()
 
                                     var t_svg = svg.transition()
Line 921: Line 1,096:
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .translate(-s[0], 0));
 
                                     .translate(-s[0], 0));
 +
                                    $('#downloadLinksRange').html(d);
 
                                 } else if (i == 3) {
 
                                 } else if (i == 3) {
 
                                     var t_svg = svg.transition()
 
                                     var t_svg = svg.transition()
Line 929: Line 1,105:
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .translate(-s[0], 0));
 
                                     .translate(-s[0], 0));
 +
                                    $('#downloadLinksRange').html(d);
 
                                 } else if (i == 4) {
 
                                 } else if (i == 4) {
 
                                       // var t_svg = svg.transition()
 
                                       // var t_svg = svg.transition()
Line 945: Line 1,122:
 
                                     area_context.x(function(d) { return xScale_context(d.dateTime); });
 
                                     area_context.x(function(d) { return xScale_context(d.dateTime); });
 
                                     context.append("path")  // append unselected context data as white lines
 
                                     context.append("path")  // append unselected context data as white lines
                                         .datum(data)  
+
                                         .datum(data)
 
                                         .attr("class", "area_context_unselected")
 
                                         .attr("class", "area_context_unselected")
 
                                         .attr("d", area_context)
 
                                         .attr("d", area_context)
Line 953: Line 1,130:
 
                                       series_color = chart_colors[i];
 
                                       series_color = chart_colors[i];
 
                                       context.append("path")
 
                                       context.append("path")
                                           .datum(data.filter(function(d){ return ( d.turbineID == Turbine_ID );} ))  
+
                                           .datum(data.filter(function(d){ return ( d.turbineID == Turbine_ID );} ))
 
                                           .attr("class", "area_context area"+(i+1))
 
                                           .attr("class", "area_context area"+(i+1))
 
                                           .attr("d", area_context)
 
                                           .attr("d", area_context)
Line 965: Line 1,142:
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .scale(width_context / (s[1] - s[0]))
 
                                     .translate(-s[0], 0));
 
                                     .translate(-s[0], 0));
 +
                                    $('#downloadLinksRange').html('All Dates');
 
                                 }
 
                                 }
 
                             })
 
                             })
Line 977: Line 1,155:
 
                                         .attr("fill",defaultColor);
 
                                         .attr("fill",defaultColor);
 
                             });
 
                             });
 
      var bWidth= 105; //button width
 
      var bHeight= 35; //button height
 
      var bSpace= 10; //space between buttons
 
      var x0= 10; //x offset
 
      var y0= 5; //y offset
 
  
 
       //adding a rect to each toggle button group
 
       //adding a rect to each toggle button group
Line 996: Line 1,168:
 
                   .attr("fill",defaultColor);
 
                   .attr("fill",defaultColor);
  
       //adding text to each toggle button group, centered  
+
       //adding text to each toggle button group, centered
 
       //within the toggle button rect
 
       //within the toggle button rect
 
       buttonGroups.append("text")
 
       buttonGroups.append("text")
Line 1,042: Line 1,214:
 
         var customBeginDate = parseCustomDate( String(document.getElementById("customBeginDate").value) );
 
         var customBeginDate = parseCustomDate( String(document.getElementById("customBeginDate").value) );
 
         var customEndDate = parseCustomDate( String(document.getElementById("customEndDate").value) );
 
         var customEndDate = parseCustomDate( String(document.getElementById("customEndDate").value) );
       
+
 
 
         if (customBeginDate == null) { var customBegin = data_start } else { var customBegin = customBeginDate } // use data start as default
 
         if (customBeginDate == null) { var customBegin = data_start } else { var customBegin = customBeginDate } // use data start as default
 
         if (customEndDate == null) { var customEnd = current_date } else { var customEnd = customEndDate } // use current date as default
 
         if (customEndDate == null) { var customEnd = current_date } else { var customEnd = customEndDate } // use current date as default
  
 
         if (customBegin > customEnd ) { customBegin = [customEnd, customEnd = customBegin][0] } // Switch fields if entered backwards
 
         if (customBegin > customEnd ) { customBegin = [customEnd, customEnd = customBegin][0] } // Switch fields if entered backwards
         if (customBegin-customEnd == 0) { customEnd = d3.timeDay.offset(customBegin, 1) } // Add 1 day interval if fields are the same  
+
         if (customBegin-customEnd == 0) { customEnd = d3.timeDay.offset(customBegin, 1) } // Add 1 day interval if fields are the same
       
+
 
 
         if (customBegin < timeslider_start) {    // Rescale the timeslider to accomodate custom range
 
         if (customBegin < timeslider_start) {    // Rescale the timeslider to accomodate custom range
 
           xScale_context.domain( [ customBegin, current_date ] );
 
           xScale_context.domain( [ customBegin, current_date ] );
Line 1,057: Line 1,229:
 
           area_context.x(function(d) { return xScale_context(d.dateTime); });
 
           area_context.x(function(d) { return xScale_context(d.dateTime); });
 
           context.append("path")  // append unselected context data as white lines
 
           context.append("path")  // append unselected context data as white lines
               .datum(data)  
+
               .datum(data)
 
               .attr("class", "area_context_unselected")
 
               .attr("class", "area_context_unselected")
 
               .attr("d", area_context)
 
               .attr("d", area_context)
Line 1,065: Line 1,237:
 
             series_color = chart_colors[i];
 
             series_color = chart_colors[i];
 
             context.append("path")
 
             context.append("path")
                 .datum(data.filter(function(d){ return ( d.turbineID == Turbine_ID );} ))  
+
                 .datum(data.filter(function(d){ return ( d.turbineID == Turbine_ID );} ))
 
                 .attr("class", "area_context area"+(i+1))
 
                 .attr("class", "area_context area"+(i+1))
 
                 .attr("d", area_context)
 
                 .attr("d", area_context)
Line 1,077: Line 1,249:
 
         .scale(width_context / (s[1] - s[0]))
 
         .scale(width_context / (s[1] - s[0]))
 
         .translate(-s[0], 0));
 
         .translate(-s[0], 0));
 +
        $('#downloadLinksRange').html(document.getElementById("customBeginDate").value + ' to ' + document.getElementById("customEndDate").value);
 
       });
 
       });
  
Line 1,117: Line 1,290:
 
           .style("text-anchor", "middle")
 
           .style("text-anchor", "middle")
 
           .style("font-size", function(){return (String( $(window).width() / 900 )+"em") })
 
           .style("font-size", function(){return (String( $(window).width() / 900 )+"em") })
           .text("Power (kW)");
+
           .text("Power (W)");
  
  
Line 1,147: Line 1,320:
 
           .style("text-anchor", "middle")
 
           .style("text-anchor", "middle")
 
           .style("font-size", function(){return (String( $(window).width() / 900 )+"em") })
 
           .style("font-size", function(){return (String( $(window).width() / 900 )+"em") })
           .text("Power (kW)");
+
           .text("Power (W)");
  
 
       focus2.append("text")
 
       focus2.append("text")
Line 1,164: Line 1,337:
  
 
       // Grid
 
       // Grid
       focus1.append("g")        
+
       focus1.append("g")
 
           .attr("class", "grid")
 
           .attr("class", "grid")
 
           .call(make_y_axis()
 
           .call(make_y_axis()
Line 1,170: Line 1,343:
 
               .tickFormat("")
 
               .tickFormat("")
 
           )
 
           )
       focus2.append("g")        
+
       focus2.append("g")
 
           .attr("class", "grid")
 
           .attr("class", "grid")
 
           .call(make_y_axis()
 
           .call(make_y_axis()
Line 1,193: Line 1,366:
 
       .attr("width", s[1] - s[0]);
 
       .attr("width", s[1] - s[0]);
 
     svg.select(".label_date").text(String(xScale_context.invert(s[0])).slice(0,21) + "  --  " + String(xScale_context.invert(s[1])).slice(0,21));    // Show the exact timestamps being focused on
 
     svg.select(".label_date").text(String(xScale_context.invert(s[0])).slice(0,21) + "  --  " + String(xScale_context.invert(s[1])).slice(0,21));    // Show the exact timestamps being focused on
 +
    var startDateRange = new Date(String(xScale_context.invert(s[0])).slice(0,21));
 +
    var endDateRange = new Date(String(xScale_context.invert(s[1])).slice(0,21));
 +
    $('#downloadLinksRange').html((startDateRange.getMonth()+1) + '/' + startDateRange.getDate() + '/' + startDateRange.getFullYear() + "  to  " + (endDateRange.getMonth()+1) + '/' + endDateRange.getDate() + '/' + endDateRange.getFullYear());
 
     svg.select(".leftHandle").attr("x", s[0]); svg.select(".rightHandle").attr("x", s[1]-8); // Move handles
 
     svg.select(".leftHandle").attr("x", s[0]); svg.select(".rightHandle").attr("x", s[1]-8); // Move handles
 
   }
 
   }
Line 1,207: Line 1,383:
 
       .attr("width", xScale_context.range().map(t.invertX, t)[1] - xScale_context.range().map(t.invertX, t)[0]);
 
       .attr("width", xScale_context.range().map(t.invertX, t)[1] - xScale_context.range().map(t.invertX, t)[0]);
 
     svg.select(".label_date").text(String(xScale_context.invert(xScale_context.range().map(t.invertX, t)[0])).slice(0,21) + "  --  " + String(xScale_context.invert(xScale_context.range().map(t.invertX, t)[1])).slice(0,21));    // Show the exact timestamps being focused on
 
     svg.select(".label_date").text(String(xScale_context.invert(xScale_context.range().map(t.invertX, t)[0])).slice(0,21) + "  --  " + String(xScale_context.invert(xScale_context.range().map(t.invertX, t)[1])).slice(0,21));    // Show the exact timestamps being focused on
 +
    var startDateRange = new Date(String(xScale_context.invert(xScale_context.range().map(t.invertX, t)[0])).slice(0,21));
 +
    var endDateRange = new Date(String(xScale_context.invert(xScale_context.range().map(t.invertX, t)[1])).slice(0,21));
 +
    $('#downloadLinksRange').html((startDateRange.getMonth()+1) + '/' + startDateRange.getDate() + '/' + startDateRange.getFullYear() + "  to  " + (endDateRange.getMonth()+1) + '/' + endDateRange.getDate() + '/' + endDateRange.getFullYear());
 
     svg.select(".leftHandle").attr("x", xScale_context.range().map(t.invertX, t)[0]); svg.select(".rightHandle").attr("x", xScale_context.range().map(t.invertX, t)[1]-8); // Move handles
 
     svg.select(".leftHandle").attr("x", xScale_context.range().map(t.invertX, t)[0]); svg.select(".rightHandle").attr("x", xScale_context.range().map(t.invertX, t)[1]-8); // Move handles
 
   }
 
   }

Latest revision as of 14:05, 21 August 2018

This widget provides a comparison tool for the Wind for Schools Portal content. It generates a table, visualizations, and interactive interface for exploring/comparing wind turbine data between participating schools.

For example:

{{#Widget:WFSPCompare}}