<commit_before>var sketchPad;
$(function() {

    $('#start-draw').on('click', function(e) {
        var size = "size=" + "640x480&";
        if (map.streetView.pano == null) {
            alert('Please switch to Street View first!');
        } else {
            var pano = "pano=" + map.streetView.location.pano + "&";
            var heading = "heading=" + map.streetView.pov.heading + "&";
            var pitch = "pitch=" + map.streetView.pov.pitch;         // var zoom = "zoom=" + map.streetView.location.pov.zoom + "&";

            var url = "http://maps.googleapis.com/maps/api/streetview?" + size + pano + heading + pitch;
            $('#street-view-image').attr("src", url);
            $('.metro').hide();
            $('.draw').show();
        }
    });

    sketchPad = createSketchpad();

    startDrawing(sketchPad);

    // Default lat and long for map on load
    var latitude = 41.881487;
    var longitude = -87.631219;

    // Set options for base google map
    var mapOptions = {
        center: new google.maps.LatLng(latitude, longitude),
        zoom: 12
    };

  // Set options for marker clusterer map
  var clusterOptions = {
    gridSize: 70,
    maxZoom: 14
  };

  var chartData;
  var dates;

  convertToX = function(date, dates) {
    return dates.indexOf(date);
  }

  resetChart = function(numDates) {
    chartData = [];
    for (var i = 0; i < numDates; i++) {
      chartData.push({
        x: i,
        report: 0,
        patch: 0
      });
    }
  }

  insertData = function(hole, data, dates) {
    completeX = convertToX(hole.completion_date, dates);
    createdX = convertToX(hole.creation_date, dates);
    var numComplete = 0;
    var numCreate = 0;
    if (completeX > -1 && completeX < dates.length) {
      numComplete = ++data[completeX].patch;
    }
    if (createdX > -1 && createdX < dates.length) {
      numCreate = ++data[createdX].report;
    }
    return [numCreate, numComplete];
  }

  var map = initialize(mapOptions);

  var mc = new MarkerClusterer(map, [], clusterOptions);

  // Search
  var infowindow = new google.maps.InfoWindow();
  var marker = "";
  var unfilled_markers = [];
  var filled_markers = [];
  var geocoder = new google.maps.Geocoder();

  function makeInfoWindowEvent(map, infowindow, contentString, marker) {
    google.maps.event.addListener(marker, 'click', function() {
      infowindow.setContent(contentString);
      infowindow.open(map, marker);
    });
  };

  function clearMarkers() {
    for (var i = 0; i < unfilled_markers.length; i++) {
      unfilled_markers[i].setMap(null);
    }
    for (var i = 0; i < filled_markers.length; i++) {
      filled_markers[i].setMap(null);
    }
  }

  function makeReportEvent(map, infowindow, event) {
    var lat = parseFloat(event.latLng.lat());
    var lng = parseFloat(event.latLng.lng());
    var latlng = new google.maps.LatLng(lat, lng);

    geocoder.geocode({
      'latLng': latlng
    }, function(results, status) {
      var address = String("'" + results[0].formatted_address + "'");
      var dropDownForm = "
Submit a report for this location
\
                <form id='reportSubmit' enctype='multipart/form-data'>\
                  <input type='hidden' name='latitude' value=" + lat + ">\
                  <input type='hidden' name='longitude' value=" + lng + ">\
                  <input type='hidden' name='address' value=" + address + ">\
                  Where is the pothole located? \
                  <select name='attribute'>\
                    <option value='CURB'>Curb Lane</option>\
                    <option value='CROSS'>Crosswalk</option>\
                    <option value='INTERSEC'>Intersection</option>\
                    <option value='TRAFFIC'>Traffic Lane</option>\
                  </select>\
                  Write a description of the pothole below (optional):\
                  <textarea name='description' cols='40' rows='4' maxLength='500' placeholder='Description here...'></textarea>\
                  Upload an image of this pothole (optional):\
                  <input type='file' name='picture'>\
                  Phone # to receive text updates about your request (optional):\
                  <input type='text' pattern='[0-9]{3}-[0-9]{3}-[0-9]{4}' name='phone' placeholder='###-###-####'>\

\

<input type='submit' value='Submit'>\
                </form>"

      infowindow.setContent(dropDownForm);
      infowindow.setPosition(event.latLng);
      infowindow.open(map);
    });
  };

  $('#map-canvas').on('submit', '#reportSubmit', function(event) {
    event.preventDefault();
    infowindow.setContent("");
    var form = $(this).serializeArray();

    $.post('/submitReport', form, function(data, textStatus, xhr) {
      if (xhr.status === 200) {
        infowindow.setContent("Your request has been submitted");
        setTimeout(function() {
          infowindow.close();
        }, 3000);
      } else {
        infowindow.setContent("Unable to process your request");
        setTimeout(function() {
          infowindow.close();
        }, 4000);
      }
    }, 'json');

  });

  getDatesBetween = function(startDate, endDate) {
    var start = new Date(startDate);
    var end = new Date(endDate);
    var between = [];
    while (start <= end) {
      start.setDate(start.getDate() + 1);
      between.push(new Date(start));
    }

    return between.map(function(date) {
      return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).slice(-2) + "-" + ("0" + date.getDate()).slice(-2);
    });
  }

  getPotholesByDate = function(startDate, endDate) {
    var dates = getDatesBetween(startDate, endDate);
    filled_markers = [];
    unfilled_markers = [];
    mc.clearMarkers();

    $.ajax({
      url: "/potholes.json",
      data: {
        all_dates: dates
      },
      success: function(data) {
        if (data == null || data.length == 0) {
          alert("There is no data for this period. Please choose another date");
        } else {
          clearMarkers();
          resetChart(dates.length);
          var yMax = 0;
          var y2Max = 0;
          for (var i = 0; i < data.length; i++) {
            var counts = insertData(data[i], chartData, dates);
            yMax = Math.max(yMax, counts[0]);
            y2Max = Math.max(y2Max, counts[1]);
            if (data[i].completion_date === null) {
              marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].latitude, data[i].longitude),
                map: map,
                icon: '/assets/red_MarkerA.png',
                optimized: true
              });
              makeInfoWindowEvent(map, infowindow, "Reported on: " + data[i].creation_date + "
" + "Street Address: " + data[i].street_address, marker);
              unfilled_markers.push(marker);
            } else {
              marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].latitude, data[i].longitude),
                map: map,
                icon: '/assets/green_MarkerA.png',
                optimized: true
              });
              makeInfoWindowEvent(map, infowindow, "Reported on: " + data[i].creation_date + "
" + "Completed Date: " + data[i].completion_date + "
" + "Street Address: " + data[i].street_address, marker);
              filled_markers.push(marker);
            }
          }

          mc.addMarkers(unfilled_markers.concat(filled_markers));

          angular.element(document.getElementById('chart')).scope().$apply(function(scope) {
            scope.dates = dates.map(function(date) {
              return date.substring(5, 10);
            });
            scope.options.axes.y.max = Math.max(yMax, y2Max);
            scope.options.axes.y2.max = Math.max(yMax, y2Max);
            scope.data = chartData;
          });
        }
      },
      dataType: "json"
    });
  }

  // Remove all markers from map if you zoom out too far, put them back when zoomed back in
  // google.maps.event.addListener(map, 'zoom_changed', function(){
  //   if (map.zoom < 7) {
  //     mc.clearMarkers();
  //   } else if (map.zoom >= 7 && mc.a.length === 0) {
  //     mc.addMarkers(unfilled_markers.concat(filled_markers));
  //   }
  // });

  // Open report form when map is clicked if zoomed in far enough
  // If report form is already open, close it on next map click
  google.maps.event.addListener(map, 'click', function(event) {
    if (map.zoom > 14 && infowindow.getContent()) {
      infowindow.close();
      infowindow.setContent("");
    } else if (map.zoom > 14) {
      makeReportEvent(map, infowindow, event);
    } else {
      infowindow.close();
    }
  });

  $("#date-pick").on('submit', function(event) {
    event.preventDefault();
    getPotholesByDate($('#start-date').val(), $('#end-date').val());
  });

  $("#filled").on('click', function() {

    if ($("#filled").prop("checked")) {
      for (var i = 0; i < filled_markers.length; ++i) {
        filled_markers[i].setVisible(false);
      }
    } else {
      for (var i = 0; i < filled_markers.length; ++i) {
        filled_markers[i].setVisible(true);
      }
    }
  });

  function search(e) {
    var code = (e.keyCode ? e.keyCode : e.which);
    var target = document.getElementById('pac-input');
    if (code == 13) { //Enter keycode
      e.preventDefault();
      geocoder.geocode({
          'address': target.value
        },
        function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            var loc = results[0].geometry.location;
            map.setZoom(17);
            map.panTo(new google.maps.LatLng(loc.lat(), loc.lng()));
          } else {
            alert("Not found: " + status);
          }
        }
      );

    }
  };

  $("#pac-input").bind("keypress", {}, search);

});
<commit_msg>upload image directly from user's computer<commit_after>var sketchPad;
$(function() {

    $('#start-draw').on('click', function(e) {
        var size = "size=" + "640x480&";
        if (map.streetView.pano == null) {
            alert('Please switch to Street View first!');
        } else {
            var pano = "pano=" + map.streetView.location.pano + "&";
            var heading = "heading=" + map.streetView.pov.heading + "&";
            var pitch = "pitch=" + map.streetView.pov.pitch;         // var zoom = "zoom=" + map.streetView.location.pov.zoom + "&";

            var url = "http://maps.googleapis.com/maps/api/streetview?" + size + pano + heading + pitch;
            $('#street-view-image').attr("src", url);
            $('.metro').hide();
            $('.draw').show();
        }
    });

    sketchPad = createSketchpad();

    startDrawing(sketchPad);

    // Default lat and long for map on load
    var latitude = 41.881487;
    var longitude = -87.631219;

    // Set options for base google map
    var mapOptions = {
        center: new google.maps.LatLng(latitude, longitude),
        zoom: 12
    };

  // Set options for marker clusterer map
  var clusterOptions = {
    gridSize: 70,
    maxZoom: 14
  };

  var chartData;
  var dates;

  convertToX = function(date, dates) {
    return dates.indexOf(date);
  }

  resetChart = function(numDates) {
    chartData = [];
    for (var i = 0; i < numDates; i++) {
      chartData.push({
        x: i,
        report: 0,
        patch: 0
      });
    }
  }

  insertData = function(hole, data, dates) {
    completeX = convertToX(hole.completion_date, dates);
    createdX = convertToX(hole.creation_date, dates);
    var numComplete = 0;
    var numCreate = 0;
    if (completeX > -1 && completeX < dates.length) {
      numComplete = ++data[completeX].patch;
    }
    if (createdX > -1 && createdX < dates.length) {
      numCreate = ++data[createdX].report;
    }
    return [numCreate, numComplete];
  }

  var map = initialize(mapOptions);

  var mc = new MarkerClusterer(map, [], clusterOptions);

  var photoURL;
  // Search
  var infowindow = new google.maps.InfoWindow();
  var marker = "";
  var unfilled_markers = [];
  var filled_markers = [];
  var geocoder = new google.maps.Geocoder();

  function makeInfoWindowEvent(map, infowindow, contentString, marker) {
    google.maps.event.addListener(marker, 'click', function() {
      infowindow.setContent(contentString);
      infowindow.open(map, marker);
    });
  };

  function clearMarkers() {
    for (var i = 0; i < unfilled_markers.length; i++) {
      unfilled_markers[i].setMap(null);
    }
    for (var i = 0; i < filled_markers.length; i++) {
      filled_markers[i].setMap(null);
    }
  }

  function makeReportEvent(map, infowindow, event) {
    var lat = parseFloat(event.latLng.lat());
    var lng = parseFloat(event.latLng.lng());
    var latlng = new google.maps.LatLng(lat, lng);

    geocoder.geocode({
      'latLng': latlng
    }, function(results, status) {
      var address = String("'" + results[0].formatted_address + "'");
      var dropDownForm = "
Submit a report for this location
\
                <form action='/upload' class='new_photo' id='new_photo' method='POST' enctype='multipart/form-data'>\
                  <input type='hidden' value=" + csrfToken + " name='authenticity_token'>\
                  Upload an image of this pothole (optional):\
                  <input id='photo_url' type='file' name='photo[url]'>\
                  <input id='upload-button' name='commit' type='submit' value='Upload'>\
                </form>\
                <form id='reportSubmit' enctype='multipart/form-data'>\
                  <input type='hidden' name='latitude' value=" + lat + ">\
                  <input type='hidden' name='longitude' value=" + lng + ">\
                  <input type='hidden' name='address' value=" + address + ">\
                  Where is the pothole located? \
                  <select name='attribute'>\
                    <option value='CURB'>Curb Lane</option>\
                    <option value='CROSS'>Crosswalk</option>\
                    <option value='INTERSEC'>Intersection</option>\
                    <option value='TRAFFIC'>Traffic Lane</option>\
                  </select>\
                  Write a description of the pothole below (optional):\
                  <textarea name='description' cols='40' rows='4' maxLength='500' placeholder='Description here...'></textarea>\
                  Phone # to receive text updates about your request (optional):\
                  <input type='text' pattern='[0-9]{3}-[0-9]{3}-[0-9]{4}' name='phone' placeholder='###-###-####'>\

\

<input type='submit' value='Submit'>\
                </form>"

      infowindow.setContent(dropDownForm);
      infowindow.setPosition(event.latLng);
      infowindow.open(map);
    });
  };

  // ================================ Photo upload ====================================
  $('#map-canvas').on('submit', '#new_photo', function(event) {
    var photoForm = document.getElementById('new_photo');
    var fileSelect = document.getElementById('photo_url');
    var uploadButton = $('#upload-button');

    event.preventDefault();

    // Update button text.
    uploadButton.val('Uploading...');

    // Create a new FormData object.
    var formData = new FormData(photoForm);

    // Set up the request.
    var xhr = new XMLHttpRequest();

    // Open the connection.
    xhr.open('POST', '/upload.json', true);

    xhr.onload = function(e) {
      photoURL = JSON.parse(xhr.responseText).url.url.url;
      if (photoURL) {
        // File(s) uploaded.
        uploadButton.val('Included');
      } else {
        alert('An error occurred!');
      }
    }

    // Send the Data.
    xhr.send(formData);
  });

  // ================================ End photo upload ====================================

  // report submit
  $('#map-canvas').on('submit', '#reportSubmit', function(event) {
    event.preventDefault();
    // infowindow.setContent("");
    var form = $(this).serializeArray();
    if (photoURL) {
      form.push({name: "mediaUrl", value: photoURL});
    }

    infowindow.setContent("Your request has been submitted");
    setTimeout(function() {
      infowindow.close();
    }, 3000);

    $.post('/submitReport', form, function(data, textStatus, xhr) {
      // if (xhr.status === 200) {
      //   infowindow.setContent("Your request has been submitted");
      //   setTimeout(function() {
      //     infowindow.close();
      //   }, 3000);
      // } else {
      //   infowindow.setContent("Unable to process your request");
      //   setTimeout(function() {
      //     infowindow.close();
      //   }, 4000);
      // }
    }, 'json');
  });

  getDatesBetween = function(startDate, endDate) {
    var start = new Date(startDate);
    var end = new Date(endDate);
    var between = [];
    while (start <= end) {
      start.setDate(start.getDate() + 1);
      between.push(new Date(start));
    }

    return between.map(function(date) {
      return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).slice(-2) + "-" + ("0" + date.getDate()).slice(-2);
    });
  }

  getPotholesByDate = function(startDate, endDate) {
    var dates = getDatesBetween(startDate, endDate);
    filled_markers = [];
    unfilled_markers = [];
    mc.clearMarkers();

    $.ajax({
      url: "/potholes.json",
      data: {
        all_dates: dates
      },
      success: function(data) {
        if (data == null || data.length == 0) {
          alert("There is no data for this period. Please choose another date");
        } else {
          clearMarkers();
          resetChart(dates.length);
          var yMax = 0;
          var y2Max = 0;
          for (var i = 0; i < data.length; i++) {
            var counts = insertData(data[i], chartData, dates);
            yMax = Math.max(yMax, counts[0]);
            y2Max = Math.max(y2Max, counts[1]);
            if (data[i].completion_date === null) {
              marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].latitude, data[i].longitude),
                map: map,
                icon: '/assets/red_MarkerA.png',
                optimized: true
              });
              makeInfoWindowEvent(map, infowindow, "Reported on: " + data[i].creation_date + "
" + "Street Address: " + data[i].street_address, marker);
              unfilled_markers.push(marker);
            } else {
              marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].latitude, data[i].longitude),
                map: map,
                icon: '/assets/green_MarkerA.png',
                optimized: true
              });
              makeInfoWindowEvent(map, infowindow, "Reported on: " + data[i].creation_date + "
" + "Completed Date: " + data[i].completion_date + "
" + "Street Address: " + data[i].street_address, marker);
              filled_markers.push(marker);
            }
          }

          mc.addMarkers(unfilled_markers.concat(filled_markers));

          angular.element(document.getElementById('chart')).scope().$apply(function(scope) {
            scope.dates = dates.map(function(date) {
              return date.substring(5, 10);
            });
            scope.options.axes.y.max = Math.max(yMax, y2Max);
            scope.options.axes.y2.max = Math.max(yMax, y2Max);
            scope.data = chartData;
          });
        }
      },
      dataType: "json"
    });
  }

  // Remove all markers from map if you zoom out too far, put them back when zoomed back in
  // google.maps.event.addListener(map, 'zoom_changed', function(){
  //   if (map.zoom < 7) {
  //     mc.clearMarkers();
  //   } else if (map.zoom >= 7 && mc.a.length === 0) {
  //     mc.addMarkers(unfilled_markers.concat(filled_markers));
  //   }
  // });

  // Open report form when map is clicked if zoomed in far enough
  // If report form is already open, close it on next map click
  google.maps.event.addListener(map, 'click', function(event) {
    if (map.zoom > 14 && infowindow.getContent()) {
      infowindow.close();
      infowindow.setContent("");
    } else if (map.zoom > 14) {
      makeReportEvent(map, infowindow, event);
    } else {
      infowindow.close();
    }
  });

  $("#date-pick").on('submit', function(event) {
    event.preventDefault();
    getPotholesByDate($('#start-date').val(), $('#end-date').val());
  });

  $("#filled").on('click', function() {

    if ($("#filled").prop("checked")) {
      for (var i = 0; i < filled_markers.length; ++i) {
        filled_markers[i].setVisible(false);
      }
    } else {
      for (var i = 0; i < filled_markers.length; ++i) {
        filled_markers[i].setVisible(true);
      }
    }
  });

  function search(e) {
    var code = (e.keyCode ? e.keyCode : e.which);
    var target = document.getElementById('pac-input');
    if (code == 13) { //Enter keycode
      e.preventDefault();
      geocoder.geocode({
          'address': target.value
        },
        function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            var loc = results[0].geometry.location;
            map.setZoom(17);
            map.panTo(new google.maps.LatLng(loc.lat(), loc.lng()));
          } else {
            alert("Not found: " + status);
          }
        }
      );

    }
  };

  $("#pac-input").bind("keypress", {}, search);

});
<|endoftext|>


<commit_before>/**
*
* This file contains 2 main parts:
* 1. myApp object with functions & behaviors organized into controllers
* 2. Initial configuration to happen on document ready
*
* These sections are further explained below.
*
* -----------------------------------------------------------------------
* ONE.
*
* The myApp object has 2 main controllers:
*
*   * MarkersCtrl
*     • Controls the creation, setting, getting, clearing,
*        event binding, and animations of google maps markers
*
*   * AjaxCtrl
*     • Handles all requests to the backend API and all responses,
*        including transforming the responses into formatted DOM elements
*     • There is only one returned method, request()
*
*
*
*  Both controllers are properties of the myApp object, and expressed as
*  Immediately-Invoking Function Expressions (IIFEs). This allows "private"
*  functions to be declared inside of them that are not returned, and so are
*  inaccessible from outside. For example, myApp.AjaxCtrl.request() is the
*  only returned function from AjaxCtrl that can be accessed elsewhere. This
*  encapsulates and shields behavior specific to the controller that is not
*  necessary to share.
*
*
*  ****** NOTE: Behavior for the slider component is located in:
*        app/assets/javascripts/components/react-slider.js
*
*
*
* -----------------------------------------------------------------------
* TWO.
*
* Initial configuration takes care of the following on document ready:
*
*   * Initializes the map with proper coordinates and zoom.
*
*   * Stores a reference to the map in the myApp object.
*
*   * Binds event handlers to the nav and date container.
*
*   * Defines the setMode() function, which event handlers use to set the
*       mode. In this case, the 'mode' refers to the type of transaction
*       filter currently being used.
*
*   * Uses the event handlers to set the initial mode to 'charge', so the
*       user does not have to select one in order to begin using the app.
*
*
* -----------------------------------------------------------------------
*/

var myApp = {

  MarkersCtrl: (function(){
    var markers = {};

    function toggleBounce() {
      if (this.getAnimation() !== null) {
        this.setAnimation(null);
      } else {
        this.setAnimation(google.maps.Animation.BOUNCE);
      }
    }

    function storeMarkerById(userId, marker) {
      if (markers[userId]) {
        markers[userId].push(marker);
      } else {
        markers[userId] = [marker];
      }
    }

    return {

      createMarker: function(LatLng, userId){
        var map = myApp.map,
            marker = new google.maps.Marker({
              position: LatLng,
              animation: google.maps.Animation.DROP,
              map: map
            });

        // Animating Listener:
        google.maps.event.addListener(marker, 'click', toggleBounce);

        // store in markers object for easy removal by batch
        storeMarkerById(userId, marker);
      },

      setMarkers: function(locations) {
        for (var i = 0, len = locations.length; i < len; i++) {
          var loc = locations[i],
              position = new google.maps.LatLng(loc.latitude, loc.longitude),
              marker = this.createMarker(position, loc.user_id);
        }
      },

      getMarkers: function(userId) {
        return (markers[userId]) ? markers[userId] : false;
      },

      toggleBounceByUserId: function(userId) {
        var markersWithId = this.getMarkers(userId);
        if (markersWithId) {
          markersWithId.forEach(function(marker) {
            google.maps.event.trigger(marker, 'click');
          });
        }
      },

      clearMarkers: function() {
        for (var userId in markers) {
          if (markers.hasOwnProperty(userId)) {
            var currentSet = markers[userId];
            for (i=0; i < currentSet.length; i++) {
              currentSet[i].setMap(null);
            }
          }
        }
        markers = {};
      }

    };

  })(),

  AjaxCtrl: (function() {

    var locationResponseHandler = function(locations) {
      for (var property in locations) {
        if (locations.hasOwnProperty(property)) {
          myApp.MarkersCtrl.setMarkers(locations[property]);
        }
      }
    };

    var transactionsResponseHandler = function(transactions) {
      var html = "";
      var formatCurrency = function(array, group) {
        group.map(function(transaction) {
          array.push("$" + transaction.amount);
        });
      };

      $('#results').html(""); // clear the list

      for (var property in transactions) {
        if (transactions.hasOwnProperty(property)) {
          var amounts = [],
              group = transactions[property],
              propertyArray = JSON.parse(property),
              userId = propertyArray[0],
              userName = propertyArray[1],
              opacityClass = getOpacityClass(group);

          formatCurrency(amounts, group);

          html += "
" +
                    userName + " - " + amounts.join(", ") +
                  "
";
        }
      }
      if (html.length === 0) {
        $('#results')
          .append(
            '
' +
              'There is no transaction data of the selected type for this date' +
            '
'
          );
      } else {
        $('#no-trans-notification').remove();
        $('#results').append(html);
      }
      // BIND EVENT HANDLERS HERE
      $('.result').on('mouseenter', function() {
        if (myApp.MarkersCtrl.getMarkers(this.id)) {
          myApp.MarkersCtrl.toggleBounceByUserId(this.id);
        } else if (this.id !== "no-trans-notification") {
          $('#results')
            .append(
              '
' +
                'There is no location data for this person on this date' +
              '
'
            );
        }
      });
      $('.result').on('mouseleave', function() {
        if (myApp.MarkersCtrl.getMarkers(this.id)) {
          myApp.MarkersCtrl.toggleBounceByUserId(this.id);
        } else {
          $('#no-loc-notification').remove();
        }
      });
    };

    var responseHandler = function(response) {
      locationResponseHandler(response.locations);
      transactionsResponseHandler(response.transactions);
    };

    var getRequestFactory = function(data, url) {
      $.ajax({
        type: 'GET',
        url: url,
        data: data
      }).success(responseHandler);
    };

    // the results returned at any time aren't huge, so this is okay
    var getOpacityClass = function(group) {
      var total = 0;
      for (i=0, len = group.length; i<len; i++) {
        total += parseFloat(group[i].amount);
      }
      if (total < 50) {
        return "light";
      } else if (total < 100) {
        return "medium-light";
      } else if (total < 150) {
        return "medium";
      } else if (total < 150) {
        return "medium-dark";
      } else if (total >= 150) {
        return "dark";
      }
    };

    return {
      request: function() {
        var mode = myApp.mode,
            date = $('#date').html();

        myApp.MarkersCtrl.clearMarkers();
        if (mode !== "all") {
          getRequestFactory({date: date, mode: mode}, '/results');
        } else if (mode === "all") {
          getRequestFactory({}, '/all');
        }
      }
    };
  })()

};

// CONFIG TO HAPPEN ON DOCUMENT READY:

$(document).ready(function() {
  function initialize() {
    var mapOptions = {

      center: new google.maps.LatLng(35.896838, -117.948875),
      zoom: 5
    };
    // capture 'map' in scope for use in making markers
    myApp.map = new google.maps.Map(document.getElementById('map-canvas'),
      mapOptions);

  }
  google.maps.event.addDomListener(window, 'load', initialize);

  // Event binding for reuse
  function bindEvents(element, action, callback) {
    $(element).on(action, callback);
  }
  // setMode is for determining what to request in Ajax calls
  bindEvents('nav a', 'click', setMode);

  bindEvents($('#date').text, 'change', myApp.AjaxCtrl.request);

  bindEvents($('nav a'), 'click', function(event) {
    $('nav a').removeClass("active");
    $(event.target).addClass("active");
  });

  // set initial mode to "charge" using bound handlers
  $('nav a:contains("CHARGE")').trigger('click');

  function setMode(event) {
    event.preventDefault();

    var mode = this.innerHTML.toLowerCase();
    myApp.mode = mode;
    if (mode === "all") {
      myApp.AjaxCtrl.request();
    }
  }

});

<commit_msg>Refactor toggleBounceByUserId to reuse toggleBounce with .call; also add missing var keyword to loop in clearMarkers<commit_after>/**
*
* This file contains 2 main parts:
* 1. myApp object with functions & behaviors organized into controllers
* 2. Initial configuration to happen on document ready
*
* These sections are further explained below.
*
* -----------------------------------------------------------------------
* ONE.
*
* The myApp object has 2 main controllers:
*
*   * MarkersCtrl
*     • Controls the creation, setting, getting, clearing,
*        event binding, and animations of google maps markers
*
*   * AjaxCtrl
*     • Handles all requests to the backend API and all responses,
*        including transforming the responses into formatted DOM elements
*     • There is only one returned method, request()
*
*
*
*  Both controllers are properties of the myApp object, and expressed as
*  Immediately-Invoking Function Expressions (IIFEs). This allows "private"
*  functions to be declared inside of them that are not returned, and so are
*  inaccessible from outside. For example, myApp.AjaxCtrl.request() is the
*  only returned function from AjaxCtrl that can be accessed elsewhere. This
*  encapsulates and shields behavior specific to the controller that is not
*  necessary to share.
*
*
*  ****** NOTE: Behavior for the slider component is located in:
*        app/assets/javascripts/components/react-slider.js
*
*
*
* -----------------------------------------------------------------------
* TWO.
*
* Initial configuration takes care of the following on document ready:
*
*   * Initializes the map with proper coordinates and zoom.
*
*   * Stores a reference to the map in the myApp object.
*
*   * Binds event handlers to the nav and date container.
*
*   * Defines the setMode() function, which event handlers use to set the
*       mode. In this case, the 'mode' refers to the type of transaction
*       filter currently being used.
*
*   * Uses the event handlers to set the initial mode to 'charge', so the
*       user does not have to select one in order to begin using the app.
*
*
* -----------------------------------------------------------------------
*/

var myApp = {

  MarkersCtrl: (function(){
    var markers = {};

    function toggleBounce() {
      if (this.getAnimation() !== null) {
        this.setAnimation(null);
      } else {
        this.setAnimation(google.maps.Animation.BOUNCE);
      }
    }

    function storeMarkerById(userId, marker) {
      if (markers[userId]) {
        markers[userId].push(marker);
      } else {
        markers[userId] = [marker];
      }
    }

    return {

      createMarker: function(LatLng, userId){
        var map = myApp.map,
            marker = new google.maps.Marker({
              position: LatLng,
              animation: google.maps.Animation.DROP,
              map: map
            });

        // Animating Listener:
        google.maps.event.addListener(marker, 'click', toggleBounce);

        // store in markers object for easy removal by batch
        storeMarkerById(userId, marker);
      },

      setMarkers: function(locations) {
        for (var i = 0, len = locations.length; i < len; i++) {
          var loc = locations[i],
              position = new google.maps.LatLng(loc.latitude, loc.longitude),
              marker = this.createMarker(position, loc.user_id);
        }
      },

      getMarkers: function(userId) {
        return (markers[userId]) ? markers[userId] : false;
      },

      toggleBounceByUserId: function(userId) {
        var markersWithId = this.getMarkers(userId);
        if (markersWithId) {
          for (var i=0, len = markersWithId.length; i < len; i++) {
            toggleBounce.call(markersWithId[i]);
          }
        }
      },

      clearMarkers: function() {
        for (var userId in markers) {
          if (markers.hasOwnProperty(userId)) {
            var currentSet = markers[userId];
            for (var i=0; i < currentSet.length; i++) {
              currentSet[i].setMap(null);
            }
          }
        }
        markers = {};
      }

    };

  })(),

  AjaxCtrl: (function() {

    var locationResponseHandler = function(locations) {
      for (var property in locations) {
        if (locations.hasOwnProperty(property)) {
          myApp.MarkersCtrl.setMarkers(locations[property]);
        }
      }
    };

    var transactionsResponseHandler = function(transactions) {
      var html = "";
      var formatCurrency = function(array, group) {
        group.map(function(transaction) {
          array.push("$" + transaction.amount);
        });
      };

      $('#results').html(""); // clear the list

      for (var property in transactions) {
        if (transactions.hasOwnProperty(property)) {
          var amounts = [],
              group = transactions[property],
              propertyArray = JSON.parse(property),
              userId = propertyArray[0],
              userName = propertyArray[1],
              opacityClass = getOpacityClass(group);

          formatCurrency(amounts, group);

          html += "
" +
                    userName + " - " + amounts.join(", ") +
                  "
";
        }
      }
      if (html.length === 0) {
        $('#results')
          .append(
            '
' +
              'There is no transaction data of the selected type for this date' +
            '
'
          );
      } else {
        $('#no-trans-notification').remove();
        $('#results').append(html);
      }
      // BIND EVENT HANDLERS HERE
      $('.result').on('mouseenter', function() {
        if (myApp.MarkersCtrl.getMarkers(this.id)) {
          myApp.MarkersCtrl.toggleBounceByUserId(this.id);
        } else if (this.id !== "no-trans-notification") {
          $('#results')
            .append(
              '
' +
                'There is no location data for this person on this date' +
              '
'
            );
        }
      });
      $('.result').on('mouseleave', function() {
        if (myApp.MarkersCtrl.getMarkers(this.id)) {
          myApp.MarkersCtrl.toggleBounceByUserId(this.id);
        } else {
          $('#no-loc-notification').remove();
        }
      });
    };

    var responseHandler = function(response) {
      locationResponseHandler(response.locations);
      transactionsResponseHandler(response.transactions);
    };

    var getRequestFactory = function(data, url) {
      $.ajax({
        type: 'GET',
        url: url,
        data: data
      }).success(responseHandler);
    };

    // the results returned at any time aren't huge, so this is okay
    var getOpacityClass = function(group) {
      var total = 0;
      for (i=0, len = group.length; i<len; i++) {
        total += parseFloat(group[i].amount);
      }
      if (total < 50) {
        return "light";
      } else if (total < 100) {
        return "medium-light";
      } else if (total < 150) {
        return "medium";
      } else if (total < 150) {
        return "medium-dark";
      } else if (total >= 150) {
        return "dark";
      }
    };

    return {
      request: function() {
        var mode = myApp.mode,
            date = $('#date').html();

        myApp.MarkersCtrl.clearMarkers();
        if (mode !== "all") {
          getRequestFactory({date: date, mode: mode}, '/results');
        } else if (mode === "all") {
          getRequestFactory({}, '/all');
        }
      }
    };
  })()

};

// CONFIG TO HAPPEN ON DOCUMENT READY:

$(document).ready(function() {
  function initialize() {
    var mapOptions = {

      center: new google.maps.LatLng(35.896838, -117.948875),
      zoom: 5
    };
    // capture 'map' in scope for use in making markers
    myApp.map = new google.maps.Map(document.getElementById('map-canvas'),
      mapOptions);

  }
  google.maps.event.addDomListener(window, 'load', initialize);

  // Event binding for reuse
  function bindEvents(element, action, callback) {
    $(element).on(action, callback);
  }
  // setMode is for determining what to request in Ajax calls
  bindEvents('nav a', 'click', setMode);

  bindEvents($('#date').text, 'change', myApp.AjaxCtrl.request);

  bindEvents($('nav a'), 'click', function(event) {
    $('nav a').removeClass("active");
    $(event.target).addClass("active");
  });

  // set initial mode to "charge" using bound handlers
  $('nav a:contains("CHARGE")').trigger('click');

  function setMode(event) {
    event.preventDefault();

    var mode = this.innerHTML.toLowerCase();
    myApp.mode = mode;
    if (mode === "all") {
      myApp.AjaxCtrl.request();
    }
  }

});

<|endoftext|>


<commit_before>$(document).ready(function() {

  $(document).endlessScroll({
    fireOnce: true,
    fireDelay: 500,
    ceaseFire: function() {
      return $('#infinite-scroll').length ? false : true;
    },
    callback: function(){
      var last = $("div.list").attr('last');
      $.ajax({
        url: '/',
          data: {
            last: last
          },
        dataType: 'script'
      });
    }
  });

  $("img.loading").ajaxStart(function(){
    $(this).removeClass('none');
  }).ajaxComplete(function(){
    $(this).addClass('none');
  });

  $(".check4contenttype").keyup(function(){
    var cur_val = $(this).val(),
        regex = /.+\.(.+)/,
        filenames = $('#filenames').data('filenames'),
        element = $('#post_content_type');
    if (regex.test(cur_val)) {
      if (typeof filenames[RegExp.$1] == 'undefined') {
        element.val(filenames['']);
      } else {
        element.val(filenames[RegExp.$1]);
      }
    } else {
      element.val(filenames['']);
    }
  });

  $("a#like_trigger").bind("ajax:success",
    function(evt, data, state, xhr){
      if (data.errors) {
        $("p#alert").html(data.errors);
      } else {
        $("div#likesize"+data.postid).html(
          " " + data.likes);
        $("div#dislikesize"+data.postid).html(
          " " + data.dislikes);
        $("div#liker").html(data.liker);
        $("div#disliker").html(data.disliker);
      }
    }
  );

  $("a#delete_trigger").bind("ajax:success",
      function(evt, data, state, xhr){
        if (data.errors) {
          $("p#alert").html(data.errors);
        } else {
          $(this).closest('div.preview_area').fadeOut();
          $("p#notice").html(data.notice);
          if (window.location.pathname != "/") {
            setTimeout(function() {
              window.location.href = "/";
            }, 2000);
          }
        }
      });
});
<commit_msg>Add automatic text selection for post url<commit_after>$(document).ready(function() {

  $(document).endlessScroll({
    fireOnce: true,
    fireDelay: 500,
    ceaseFire: function() {
      return $('#infinite-scroll').length ? false : true;
    },
    callback: function(){
      var last = $("div.list").attr('last');
      $.ajax({
        url: '/',
          data: {
            last: last
          },
        dataType: 'script'
      });
    }
  });

  $("img.loading").ajaxStart(function(){
    $(this).removeClass('none');
  }).ajaxComplete(function(){
    $(this).addClass('none');
  });

  $(".check4contenttype").keyup(function(){
    var cur_val = $(this).val(),
        regex = /.+\.(.+)/,
        filenames = $('#filenames').data('filenames'),
        element = $('#post_content_type');
    if (regex.test(cur_val)) {
      if (typeof filenames[RegExp.$1] == 'undefined') {
        element.val(filenames['']);
      } else {
        element.val(filenames[RegExp.$1]);
      }
    } else {
      element.val(filenames['']);
    }
  });

  $("a#like_trigger").bind("ajax:success",
    function(evt, data, state, xhr){
      if (data.errors) {
        $("p#alert").html(data.errors);
      } else {
        $("div#likesize"+data.postid).html(
          " " + data.likes);
        $("div#dislikesize"+data.postid).html(
          " " + data.dislikes);
        $("div#liker").html(data.liker);
        $("div#disliker").html(data.disliker);
      }
    }
  );

  $("a#delete_trigger").bind("ajax:success",
      function(evt, data, state, xhr){
        if (data.errors) {
          $("p#alert").html(data.errors);
        } else {
          $(this).closest('div.preview_area').fadeOut();
          $("p#notice").html(data.notice);
          if (window.location.pathname != "/") {
            setTimeout(function() {
              window.location.href = "/";
            }, 2000);
          }
        }
      });

  $('#post_url').focus(function(event) {
    var target = $(event.target);
    setTimeout(function() {
      target.select();
    }, 100);
  });

});
<|endoftext|>


<commit_before>$(function () {

  'use strict';

  var $blockLabels;

  // Change appearance of block labels when interacting
  $blockLabels = $('.block-label input[type="radio"], .block-label input[type="checkbox"]');
  new GOVUK.SelectionButtons($blockLabels);

  // Browser confirm dialog
  $(document).on('click', '[data-confirm]', function (e) {
    e.preventDefault();
    if (window.confirm($(this).data('confirm'))) {
      window.location.href = $(this).attr('href');
    }
  });

  function getAge(d1, d2){
    d2 = d2 || new Date();
    var diff = d2.getTime() - d1.getTime();
    return Math.floor(diff / (1000 * 60 * 60 * 24 * 365.25));
  }

  $('body').on('change', '.known-date input', function() {

    var dob, el,
        known = $(this).closest('.known-date'),
        year = known.find('.year').val(),
        month = known.find('.month').val(),
        day = known.find('.day').val();

    el = $(this).closest('.additional-visitor').find('h2');

    if (year!=='' && month !== '' && day !== '') {
      dob = new Date(year, month-1, day);

      el.find('small').remove();

      if (getAge(dob) > 17) {
        el.append(' Adult');
      } else {
        el.append(' Child');
      }
    }
  });

  $('.known-date input').change();

  $('#ad-help').on('click', function () {
    ga('send', 'event', 'external-link', 'ad-help');
  });

  $('#confirmation_no_vo').on('change', function() {
    var dis = $('#confirmation_no_pvo');

    if ($(this).is(':checked')) {
      dis.attr('disabled', false);
      dis.closest('label').removeClass('disabled');
    } else {
      if (dis.is(':checked')) { dis.click(); }
      dis.attr('disabled', true);
      dis.closest('label').addClass('disabled');
    }
  }).change();

  $('.BookingCalendar input[type=radio]').on('click', function() {
    var date = moj.Helpers.dateFromIso($(this).val()),
      days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
      months = ['January','February','March','April','May','June','July','August','September','October','November','December'];

    $(this).closest('.BookingCalendar').siblings('p').find('span').text(days[date.getDay()] +' '+ date.getDate() +' '+ months[date.getMonth()]);
  });
});

moj.are_cookies_enabled = function () {
  'use strict';

  var cookieEnabled = (navigator.cookieEnabled) ? true : false;

  if (typeof navigator.cookieEnabled === 'undefined' && !cookieEnabled) {
    document.cookie = 'testcookie';
    cookieEnabled = (document.cookie.indexOf('testcookie') !== -1) ? true : false;
  }
  return (cookieEnabled);
};

moj.show_cookie_message = function () {
  'use strict';

  if (!moj.are_cookies_enabled() && $('body.visit').length) {
    $('noscript').after( $('noscript').text() );
  }
}();

moj.focusAriaAlert = function() {
  'use strict';

  var ariaAlert = document.getElementById('error-summary');
  if(ariaAlert){
    $(ariaAlert).focus();
  }
}();
<commit_msg>Comment some shameful JavaScript<commit_after>$(function () {

  'use strict';

  var $blockLabels;

  // Change appearance of block labels when interacting
  $blockLabels = $('.block-label input[type="radio"], .block-label input[type="checkbox"]');
  new GOVUK.SelectionButtons($blockLabels);

  // Browser confirm dialog
  $(document).on('click', '[data-confirm]', function (e) {
    e.preventDefault();
    if (window.confirm($(this).data('confirm'))) {
      window.location.href = $(this).attr('href');
    }
  });

  function getAge(d1, d2){
    d2 = d2 || new Date();
    var diff = d2.getTime() - d1.getTime();
    return Math.floor(diff / (1000 * 60 * 60 * 24 * 365.25));
  }

  // Display adult/child labels against visitors when entering DOB
  $('body').on('change', '.known-date input', function() {

    var dob, el,
        known = $(this).closest('.known-date'),
        year = known.find('.year').val(),
        month = known.find('.month').val(),
        day = known.find('.day').val();

    el = $(this).closest('.additional-visitor').find('h2');

    if (year!=='' && month !== '' && day !== '') {
      dob = new Date(year, month-1, day);

      el.find('small').remove();

      if (getAge(dob) > 17) {
        el.append(' Adult');
      } else {
        el.append(' Child');
      }
    }
  });

  $('.known-date input').change();

  $('#ad-help').on('click', function () {
    ga('send', 'event', 'external-link', 'ad-help');
  });

  // Staff processing form

  // Only enable PVO when VO is checked
  $('#confirmation_no_vo').on('change', function() {
    var dis = $('#confirmation_no_pvo');

    if ($(this).is(':checked')) {
      dis.attr('disabled', false);
      dis.closest('label').removeClass('disabled');
    } else {
      if (dis.is(':checked')) { dis.click(); }
      dis.attr('disabled', true);
      dis.closest('label').addClass('disabled');
    }
  }).change();

  // Display date from ISO-8601 format
  $('.BookingCalendar input[type=radio]').on('click', function() {
    var date = moj.Helpers.dateFromIso($(this).val()),
      days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
      months = ['January','February','March','April','May','June','July','August','September','October','November','December'];

    $(this).closest('.BookingCalendar').siblings('p').find('span').text(days[date.getDay()] +' '+ date.getDate() +' '+ months[date.getMonth()]);
  });
});

moj.are_cookies_enabled = function () {
  'use strict';

  var cookieEnabled = (navigator.cookieEnabled) ? true : false;

  if (typeof navigator.cookieEnabled === 'undefined' && !cookieEnabled) {
    document.cookie = 'testcookie';
    cookieEnabled = (document.cookie.indexOf('testcookie') !== -1) ? true : false;
  }
  return (cookieEnabled);
};

moj.show_cookie_message = function () {
  'use strict';

  if (!moj.are_cookies_enabled() && $('body.visit').length) {
    $('noscript').after( $('noscript').text() );
  }
}();

moj.focusAriaAlert = function() {
  'use strict';

  var ariaAlert = document.getElementById('error-summary');
  if(ariaAlert){
    $(ariaAlert).focus();
  }
}();
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2016 SKYARCH NETWORKS INC.
//
// This software is released under the MIT License.
//
// http://opensource.org/licenses/mit-license.php
//

//    このファイルには、全体で使いたい関数を定義する。

var t = function (scope, options) {
  return I18n.t(scope, options);
};

//show loading gif when a button is clicked

var bootstrap_alert_div = function (klass, content) {
    var alertDiv = $("
");
    content = content.replace(/\n/g, "
");
    alertDiv.addClass("alert").addClass(klass);

    alertDiv.html(content);
    return alertDiv;
};

var overwrite_by_alert = function (button, extraClass, content) {
  var target = button.parent();
  var klass  = "";
  if (extraClass) {klass += extraClass;}

  var alertDiv = bootstrap_alert_div(klass, content);

  target.empty();
  target.append(alertDiv);
  return alertDiv;
};

var overwrite_by_loading_alert = function (button, content) {
  var progress = overwrite_by_alert(button, "", content);
  progress.prepend(loadGif);
  return progress;
};

var show_loading = function (target) {
  var load = $("" + t('common.msg.loading') + "");
  load.prepend(loadGif);
  target.html(load);
};

var get_query_strings = function () {
  var query_string = window.location.search;
  query_string = query_string.substr(1, query_string.length);

  var query_string_obj = {};
  var items = query_string.split('&');
  $.each(items, function () {
    var item = this;
    var splited_item = item.split('=');
    var key = splited_item[0];
    var val = splited_item[1];
    query_string_obj[key] = val;
  });
  return query_string_obj;
};

var get_query_string = function (key) {
  return get_query_strings()[key];
};

// Disable default behaviors of event
var cancel_default_event = function (event) {
  event.preventDefault();
  event.stopPropagation();
  return false;
};

var add_filename_label = function (filename, before) {
  $(".filename_label").remove();
  before.after($("").addClass("label label-default filename_label").text(filename));
};

// TODO: テキストファイル以外が投げられた場合は読み込まないようにしたい
var file_drop_func = function (id) {
  return function (e) {
    cancel_default_event(e);
    var file = e.originalEvent.dataTransfer.files[0];

    var fileReader = new FileReader();
    fileReader.onload = function (e) {
      $(id).val(e.target.result).trigger("change");
      add_filename_label(file.name, $(id));
    };
    fileReader.readAsText(file);

    if (id === "#keypair_value") {
      $("#keypair_name").val(file.name.replace(/\.\w+$/, ''));
    }
  };
};

$(document).ready(function () {
  // Drag'n'drop
  // TODO: id ではなく class で指定するようにしたい
  _.each(["#keypair_value", "#cf_template_value", "#add_modify_value"], function (id) {
    $(document).on("drop", id, file_drop_func(id));
    $(document).on("dragenter", id, cancel_default_event);
    $(document).on("dragover", id, cancel_default_event);
    $(id).change(function () { $(".filename_label").remove(); });
  });
});

var masking_input_form = function (btn, target) {
  target.attr("type", "password");
  btn.children("span.glyphicon").removeClass("glyphicon-eye-close").addClass("glyphicon-eye-open");
};

var unmasking_input_form = function (btn, target) {
  target.attr("type", "text");
  btn.children("span.glyphicon").removeClass("glyphicon-eye-open").addClass("glyphicon-eye-close");
};

var toggle_input_masking = function (btn, target) {
  if (target.attr("type") === "text") {
    masking_input_form(btn, target);
  }
  else {
    unmasking_input_form(btn, target);
  }
};

var create_masked_input = function (input) {
  var target_id = input.attr("id");
  var btn_toggle = $("<button>", {
    class: "btn btn-default toggle-input-masking",
    for: target_id
  }).append( glyphicon("eye-open") );
  var input_group_btn = $("", {class: "input-group-btn"}).append( btn_toggle );

  input.wrap( $("
").addClass("input-group") );
  input.parent().append(input_group_btn);

  masking_input_form(input_group_btn, input);
};

$(document).ready(function() {
  create_masked_input( $("input.form-control-masked") );

  $(document).on("click", ".toggle-input-masking", function (e) {
    cancel_default_event(e);
    toggle_input_masking($(this), $("#" + $(this).attr("for")) );
  });
});

// for websocket
var ws_connector = function (kind, id) {
  var ws_protocol = (("https:" == document.location.protocol) ? "wss:" : "ws:");
  return new WebSocket(ws_protocol + '//' + location.hostname + '/ws/' + kind + '/' + id );
};

/* form-validation */
$(document).ready(function () {
  var inputs = $('input').filter("[type=text],[type=password],[type=email]").filter(':not(.allow-empty)');

  var is_input_filled = function() {
    var is_filled = true;

    inputs.each(function () {
      if ( $(this).val().length === 0 ) {
        is_filled = false;
        return false;
      }
      if ( $(this).attr("type") === "password" && $(this).val().indexOf(" ") !== -1 ) {
        is_filled = false;
        return false;
      }
    });

    return is_filled;
  };

  var toggle_input = function () {
    var submit = $(".create");

    if ( is_input_filled() ) {
      submit.removeAttr('disabled');
    }
    else {
      submit.attr('disabled', 'disabled');
    }
  };

  toggle_input();

  inputs.bind("keyup change", function () {
    toggle_input();
  });
});

// allow textfile drop
$.event.props.push("dataTransfer");

$(document).on("dragover", ".allow_textfile_drop", function(e){
  e.preventDefault();
});

$(document).on("drop", ".allow_textfile_drop", function(e){
  self = this;
  e.preventDefault();
  var file = e.dataTransfer.files[0];
  var fileReader = new FileReader();
  fileReader.onloadend = function(){
    $(self).val(fileReader.result).trigger("input");
  };
  fileReader.readAsText(file);
});

// setup clipboard.js
new Clipboard('[data-clipboard]').on('success', function (e) {
  var btn = $(e.trigger);
  var target = btn.find('.copied-hint-target');
  var hint_text = btn.attr('data-copied-hint');
  var orig_text = target.text();
  btn.attr('disabled', true);
  target.text(hint_text);
  setTimeout(function () {
    target.text(orig_text);
    btn.attr('disabled', null);
  }, 1000);
});
<commit_msg>Fix: ファイルのパーミッションを修正<commit_after>//
// Copyright (c) 2013-2016 SKYARCH NETWORKS INC.
//
// This software is released under the MIT License.
//
// http://opensource.org/licenses/mit-license.php
//

//    このファイルには、全体で使いたい関数を定義する。

var t = function (scope, options) {
  return I18n.t(scope, options);
};

//show loading gif when a button is clicked

var bootstrap_alert_div = function (klass, content) {
    var alertDiv = $("
");
    content = content.replace(/\n/g, "
");
    alertDiv.addClass("alert").addClass(klass);

    alertDiv.html(content);
    return alertDiv;
};

var overwrite_by_alert = function (button, extraClass, content) {
  var target = button.parent();
  var klass  = "";
  if (extraClass) {klass += extraClass;}

  var alertDiv = bootstrap_alert_div(klass, content);

  target.empty();
  target.append(alertDiv);
  return alertDiv;
};

var overwrite_by_loading_alert = function (button, content) {
  var progress = overwrite_by_alert(button, "", content);
  progress.prepend(loadGif);
  return progress;
};

var show_loading = function (target) {
  var load = $("" + t('common.msg.loading') + "");
  load.prepend(loadGif);
  target.html(load);
};

var get_query_strings = function () {
  var query_string = window.location.search;
  query_string = query_string.substr(1, query_string.length);

  var query_string_obj = {};
  var items = query_string.split('&');
  $.each(items, function () {
    var item = this;
    var splited_item = item.split('=');
    var key = splited_item[0];
    var val = splited_item[1];
    query_string_obj[key] = val;
  });
  return query_string_obj;
};

var get_query_string = function (key) {
  return get_query_strings()[key];
};

// Disable default behaviors of event
var cancel_default_event = function (event) {
  event.preventDefault();
  event.stopPropagation();
  return false;
};

var add_filename_label = function (filename, before) {
  $(".filename_label").remove();
  before.after($("").addClass("label label-default filename_label").text(filename));
};

// TODO: テキストファイル以外が投げられた場合は読み込まないようにしたい
var file_drop_func = function (id) {
  return function (e) {
    cancel_default_event(e);
    var file = e.originalEvent.dataTransfer.files[0];

    var fileReader = new FileReader();
    fileReader.onload = function (e) {
      $(id).val(e.target.result).trigger("change");
      add_filename_label(file.name, $(id));
    };
    fileReader.readAsText(file);

    if (id === "#keypair_value") {
      $("#keypair_name").val(file.name.replace(/\.\w+$/, ''));
    }
  };
};

$(document).ready(function () {
  // Drag'n'drop
  // TODO: id ではなく class で指定するようにしたい
  _.each(["#keypair_value", "#cf_template_value", "#add_modify_value"], function (id) {
    $(document).on("drop", id, file_drop_func(id));
    $(document).on("dragenter", id, cancel_default_event);
    $(document).on("dragover", id, cancel_default_event);
    $(id).change(function () { $(".filename_label").remove(); });
  });
});

var masking_input_form = function (btn, target) {
  target.attr("type", "password");
  btn.children("span.glyphicon").removeClass("glyphicon-eye-close").addClass("glyphicon-eye-open");
};

var unmasking_input_form = function (btn, target) {
  target.attr("type", "text");
  btn.children("span.glyphicon").removeClass("glyphicon-eye-open").addClass("glyphicon-eye-close");
};

var toggle_input_masking = function (btn, target) {
  if (target.attr("type") === "text") {
    masking_input_form(btn, target);
  }
  else {
    unmasking_input_form(btn, target);
  }
};

var create_masked_input = function (input) {
  var target_id = input.attr("id");
  var btn_toggle = $("<button>", {
    class: "btn btn-default toggle-input-masking",
    for: target_id
  }).append( glyphicon("eye-open") );
  var input_group_btn = $("", {class: "input-group-btn"}).append( btn_toggle );

  input.wrap( $("
").addClass("input-group") );
  input.parent().append(input_group_btn);

  masking_input_form(input_group_btn, input);
};

$(document).ready(function() {
  create_masked_input( $("input.form-control-masked") );

  $(document).on("click", ".toggle-input-masking", function (e) {
    cancel_default_event(e);
    toggle_input_masking($(this), $("#" + $(this).attr("for")) );
  });
});

// for websocket
var ws_connector = function (kind, id) {
  var ws_protocol = (("https:" == document.location.protocol) ? "wss:" : "ws:");
  return new WebSocket(ws_protocol + '//' + location.hostname + '/ws/' + kind + '/' + id );
};

/* form-validation */
$(document).ready(function () {
  var inputs = $('input').filter("[type=text],[type=password],[type=email]").filter(':not(.allow-empty)');

  var is_input_filled = function() {
    var is_filled = true;

    inputs.each(function () {
      if ( $(this).val().length === 0 ) {
        is_filled = false;
        return false;
      }
      if ( $(this).attr("type") === "password" && $(this).val().indexOf(" ") !== -1 ) {
        is_filled = false;
        return false;
      }
    });

    return is_filled;
  };

  var toggle_input = function () {
    var submit = $(".create");

    if ( is_input_filled() ) {
      submit.removeAttr('disabled');
    }
    else {
      submit.attr('disabled', 'disabled');
    }
  };

  toggle_input();

  inputs.bind("keyup change", function () {
    toggle_input();
  });
});

// allow textfile drop
$.event.props.push("dataTransfer");

$(document).on("dragover", ".allow_textfile_drop", function(e){
  e.preventDefault();
});

$(document).on("drop", ".allow_textfile_drop", function(e){
  self = this;
  e.preventDefault();
  var file = e.dataTransfer.files[0];
  var fileReader = new FileReader();
  fileReader.onloadend = function(){
    $(self).val(fileReader.result).trigger("input");
  };
  fileReader.readAsText(file);
});

// setup clipboard.js
new Clipboard('[data-clipboard]').on('success', function (e) {
  var btn = $(e.trigger);
  var target = btn.find('.copied-hint-target');
  var hint_text = btn.attr('data-copied-hint');
  var orig_text = target.text();
  btn.attr('disabled', true);
  target.text(hint_text);
  setTimeout(function () {
    target.text(orig_text);
    btn.attr('disabled', null);
  }, 1000);
});
<|endoftext|>


<commit_before>'use strict';
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withRouter, matchPath } from 'react-router-dom';
import c from 'classnames';

import { closeDownloadModal as closeDownloadModalAction } from '../actions/action-creators';
import PageHeader from '../components/page-header';
import PageFooter from '../components/page-footer';
import ModalDownload from '../components/modal-download/';

function App(props) {
  const { children, location, downloadModal, closeDownloadModal } = props;

  const pageClass = children.props.children.find(child => {
    const match = matchPath(location.pathname, {
      path: child.props.path,
    });
    return match && match.isExact;
  }).props.pageClass;

  return (

      <PageHeader />

        {children}

      {downloadModal.open && (
        <ModalDownload
          downloadType={downloadModal.downloadType}
          country={downloadModal.country}
          area={downloadModal.area}
          location={downloadModal.location}
          project={downloadModal.project}
          onModalClose={closeDownloadModal}
          revealed={downloadModal.open}
        />
      )}
      <PageFooter measurements={null} />

  );
}

App.propTypes = {
  children: PropTypes.element,
  location: PropTypes.object,
  downloadModal: PropTypes.object.isRequired,
  closeDownloadModal: PropTypes.func.isRequired,
};

// /////////////////////////////////////////////////////////////////// //
// Connect functions

function selector(state) {
  return {
    downloadModal: state.downloadModal,
  };
}

function dispatcher(dispatch) {
  return {
    closeDownloadModal: (...args) =>
      dispatch(closeDownloadModalAction(...args)),
  };
}

module.exports = connect(selector, dispatcher)(withRouter(App));
<commit_msg>If page not found, redirect to home<commit_after>'use strict';
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withRouter, matchPath, Redirect } from 'react-router-dom';
import c from 'classnames';

import { closeDownloadModal as closeDownloadModalAction } from '../actions/action-creators';
import PageHeader from '../components/page-header';
import PageFooter from '../components/page-footer';
import ModalDownload from '../components/modal-download/';

function App(props) {
  const { children, location, downloadModal, closeDownloadModal } = props;

  const matchedChild = children.props.children.find(child => {
    const match = matchPath(location.pathname, {
      path: child.props.path,
    });
    return match && match.isExact;
  });

  if (!matchedChild) {
    return <Redirect to="/" />;
  }

  const pageClass = matchedChild.props.pageClass;

  return (

      <PageHeader />

        {children}

      {downloadModal.open && (
        <ModalDownload
          downloadType={downloadModal.downloadType}
          country={downloadModal.country}
          area={downloadModal.area}
          location={downloadModal.location}
          project={downloadModal.project}
          onModalClose={closeDownloadModal}
          revealed={downloadModal.open}
        />
      )}
      <PageFooter measurements={null} />

  );
}

App.propTypes = {
  children: PropTypes.element,
  location: PropTypes.object,
  downloadModal: PropTypes.object.isRequired,
  closeDownloadModal: PropTypes.func.isRequired,
};

// /////////////////////////////////////////////////////////////////// //
// Connect functions

function selector(state) {
  return {
    downloadModal: state.downloadModal,
  };
}

function dispatcher(dispatch) {
  return {
    closeDownloadModal: (...args) =>
      dispatch(closeDownloadModalAction(...args)),
  };
}

module.exports = connect(selector, dispatcher)(withRouter(App));
<|endoftext|>


<commit_before>/*requires core.js*/
/*requires load.js*/
/*requires ajax.js*/
/*requires dom.js*/
/*requires selector.js*/
/*requires ua.js*/
/*requires event.js*/
/*requires ui.js*/
/**
 * nova.ui.tab
 * tab 切换，若没有给定 id ，则对 class 为 tab 的所有元素执行函数
 */
nova.ui.tab = function(elm) {
    var elt = elm || ".nova-tab",
	hd = nova.dom.selector(".item", nova.dom.selector(elt + " .hd")[0]),
	bd = nova.dom.selector(".item", nova.dom.selector(elt + " .bd")[0]),
	init,
	hidden,
	toggle,
	i,
	len;

    hidden = function() {
	for (i = 0, len = bd.length; i < len; i++) {
	    console.log(bd[i]);
	    nova.dom.removeClass(hd[i], "selected");
	    nova.dom.addClass(bd[i], "hidden");
	}
    };

    toggle = function(e) {
	e = e || window.event;
	var target = e.target || e.srcElement;

	// 确保焦点是

	if (target.nodeName === "A") {
	    target = target.parentNode;
	}

	// 隐藏所有tab内容，并且删除所有选中状态
	hidden();

	// 给当前标题加上选中状态
	nova.dom.addClass(target, "selected");
	// 显示当前tab内容
	nova.dom.removeClass(bd[target.index], "hidden");
    };

    // 添加事件
    for (i = 0, len = hd.length; i < len; i++) {
	hd[i].index = i;
	nova.Event.add(hd[i], "mouseover", toggle);
    }

    // 初始化, 只显示第一个tab
    hidden();
    nova.dom.addClass(hd[0], "selected");
    nova.dom.removeClass(bd[0], "hidden");
};

<commit_msg>delete console<commit_after>/*requires core.js*/
/*requires load.js*/
/*requires ajax.js*/
/*requires dom.js*/
/*requires selector.js*/
/*requires ua.js*/
/*requires event.js*/
/*requires ui.js*/
/**
 * nova.ui.tab
 * tab 切换，若没有给定 id ，则对 class 为 tab 的所有元素执行函数
 */
nova.ui.tab = function(elm) {
    var elt = elm || ".nova-tab",
	hd = nova.dom.selector(".item", nova.dom.selector(elt + " .hd")[0]),
	bd = nova.dom.selector(".item", nova.dom.selector(elt + " .bd")[0]),
	init,
	hidden,
	toggle,
	i,
	len;

    hidden = function() {
	for (i = 0, len = bd.length; i < len; i++) {
	    nova.dom.removeClass(hd[i], "selected");
	    nova.dom.addClass(bd[i], "hidden");
	}
    };

    toggle = function(e) {
	e = e || window.event;
	var target = e.target || e.srcElement;

	// 确保焦点是

	if (target.nodeName === "A") {
	    target = target.parentNode;
	}

	// 隐藏所有tab内容，并且删除所有选中状态
	hidden();

	// 给当前标题加上选中状态
	nova.dom.addClass(target, "selected");
	// 显示当前tab内容
	nova.dom.removeClass(bd[target.index], "hidden");
    };

    // 添加事件
    for (i = 0, len = hd.length; i < len; i++) {
	hd[i].index = i;
	nova.Event.add(hd[i], "mouseover", toggle);
    }

    // 初始化, 只显示第一个tab
    hidden();
    nova.dom.addClass(hd[0], "selected");
    nova.dom.removeClass(bd[0], "hidden");
};

<|endoftext|>


<commit_before>import ko from 'knockout';
import uuid from 'uuid';

const TOUCH_TOLERANCE_IN_PIXELS = 12;

// AVU == AnaVis Units

function registerEventListenerWithTeardown(element, event, handler) {
  element.addEventListener(event, handler);
  ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener(event, handler));
}

function getOperationsInfo(element, event, work) {
  const totalWorkLengthInPixels = element.clientWidth;
  const touchOffsetInPixels = event.clientX - element.offsetLeft;
  const totalParts = work.parts().length;
  const totalWorkLengthInAvus = work.parts().reduce((sum, currentPart) => sum + currentPart.length(), 0);
  const avusPerPixel = totalWorkLengthInAvus / totalWorkLengthInPixels;
  const touchOffsetInAvus = touchOffsetInPixels * avusPerPixel;
  const touchToleranceInAvus = TOUCH_TOLERANCE_IN_PIXELS * avusPerPixel;

  for (let currentPartIndex = 0, currentBorderOffsetInAvus = 0; currentPartIndex < totalParts; currentPartIndex += 1) {
    const currentPartLength = work.parts()[currentPartIndex].length();
    const leftBorderOffsetInAvus = currentBorderOffsetInAvus;
    const rightBorderOffsetInAvus = leftBorderOffsetInAvus + currentPartLength;
    const isTouchWithinCurrentPart = touchOffsetInAvus >= leftBorderOffsetInAvus && touchOffsetInAvus < rightBorderOffsetInAvus;
    if (isTouchWithinCurrentPart) {
      const info = {};
      info.isResizing = false;
      info.index = currentPartIndex;
      info.avusPerPixel = avusPerPixel;
      info.initialTouchOffsetInAvus = touchOffsetInAvus;
      info.touchOffsetWithinPartInAvus = touchOffsetInAvus - leftBorderOffsetInAvus;

      if (touchOffsetInAvus <= (leftBorderOffsetInAvus + touchToleranceInAvus) && currentPartIndex !== 0) {
        info.isResizing = true;
        info.leftIndex = currentPartIndex - 1;
        info.rightIndex = currentPartIndex;
        info.initalLeftPartLengthInAvus = work.parts()[currentPartIndex - 1].length();
        info.initalRightPartLengthInAvus = work.parts()[currentPartIndex].length();
      } else if (touchOffsetInAvus >= (rightBorderOffsetInAvus - touchToleranceInAvus) && currentPartIndex !== (totalParts - 1)) {
        info.isResizing = true;
        info.leftIndex = currentPartIndex;
        info.rightIndex = currentPartIndex + 1;
        info.initalLeftPartLengthInAvus = work.parts()[currentPartIndex].length();
        info.initalRightPartLengthInAvus = work.parts()[currentPartIndex + 1].length();
      }

      return info;
    }

    currentBorderOffsetInAvus = rightBorderOffsetInAvus;
  }

  return undefined;
}

function applyMovement(currentOperationsInfo, work, element) {
  if (!currentOperationsInfo || !currentOperationsInfo.isResizing) {
    return;
  }
  const minPartLengthInAvus = TOUCH_TOLERANCE_IN_PIXELS * currentOperationsInfo.avusPerPixel;
  const touchOffsetInPixels = event.clientX - element.offsetLeft;
  const touchOffsetInAvus = touchOffsetInPixels * currentOperationsInfo.avusPerPixel;
  const distanceInAvus = Math.round(touchOffsetInAvus - currentOperationsInfo.initialTouchOffsetInAvus);
  const newLeftPartLength = currentOperationsInfo.initalLeftPartLengthInAvus + distanceInAvus;
  const newRightPartLength = currentOperationsInfo.initalRightPartLengthInAvus - distanceInAvus;
  if (newLeftPartLength >= minPartLengthInAvus && newRightPartLength >= minPartLengthInAvus) {
    work.parts()[currentOperationsInfo.leftIndex].length(newLeftPartLength);
    work.parts()[currentOperationsInfo.rightIndex].length(newRightPartLength);
  }
}

function applyRelease(currentOperationsInfo, work, element, event, app) {
  if (!currentOperationsInfo || currentOperationsInfo.isResizing) {
    return;
  }
  const newInfo = getOperationsInfo(element, event, work);
  if (newInfo && !newInfo.isResizing && newInfo.index === currentOperationsInfo.index) {
    const clickedPart = work.parts()[newInfo.index];

    if (app.currentTool() === 'default') {
      app.currentPart(clickedPart);
    } else if (app.currentTool() === 'scissors') {
      splitPart(work, newInfo.index, newInfo.touchOffsetWithinPartInAvus);
      app.currentPart(work.parts()[newInfo.index + 1]);
    } else if (app.currentTool() === 'glue') {
      console.log('right or left is here the question!');
    }
    event.stopPropagation();
  }
}

function toggleResizeCursor(element, currentOperationsInfo) {
  if (currentOperationsInfo && currentOperationsInfo.isResizing) {
    element.classList.add('u-col-resize');
  } else {
    element.classList.remove('u-col-resize');
  }
}

function register() {
  ko.bindingHandlers.partOperations = {
    init: function (element, valueAccessor) {
      const app = valueAccessor().app;
      const work = valueAccessor().work;

      registerEventListenerWithTeardown(element, 'mousedown', onMouseDown);
      registerEventListenerWithTeardown(element, 'mouseup', onMouseUp);
      registerEventListenerWithTeardown(element, 'mouseleave', onMouseLeave);
      registerEventListenerWithTeardown(element, 'mousemove', onMouseMove);

      let currentOperationsInfo = undefined;

      function onMouseDown(event) {
        currentOperationsInfo = getOperationsInfo(element, event, work);
        toggleResizeCursor(element, currentOperationsInfo);
      }

      function onMouseUp(event) {
        applyRelease(currentOperationsInfo, work, element, event, app);
        currentOperationsInfo = undefined;
        toggleResizeCursor(element, undefined);
      }

      function onMouseLeave(event) {
        currentOperationsInfo = undefined;
        toggleResizeCursor(element, currentOperationsInfo);
      }

      function onMouseMove(event) {
        applyMovement(currentOperationsInfo, work, element);
        toggleResizeCursor(element, currentOperationsInfo || getOperationsInfo(element, event, work));
      }
    }
  };
}

////// TODO EXTRACT ///////////////////////////////

function splitPart(work, partIndex, splitPoint) {
  console.log('YAY');
  const oldPartsArray = work.parts();
  const partToSplit = oldPartsArray[partIndex];
  const originalLength = partToSplit.length();

  const leftClone = clonePart(partToSplit);
  const rightClone = clonePart(partToSplit);
  leftClone.length(splitPoint);
  rightClone.length(originalLength - splitPoint);

  const newPartsArray = [];
  oldPartsArray.slice(0, partIndex).forEach(x => newPartsArray.push(x));
  newPartsArray.push(leftClone);
  newPartsArray.push(rightClone);
  oldPartsArray.slice(partIndex + 1).forEach(x => newPartsArray.push(x));

  work.parts(newPartsArray);
}

function clonePart(part) {
  return {
    id: ko.observable(newId()),
    length: ko.observable(part.length()),
    color: ko.observable(part.color()),
    name: ko.observable(part.name())
  };
}

function newId() {
  return uuid.v4();
}

export default { register };
<commit_msg>Prohibit resizing functionality in scissors mode<commit_after>import ko from 'knockout';
import uuid from 'uuid';

const TOUCH_TOLERANCE_IN_PIXELS = 12;

// AVU == AnaVis Units

function registerEventListenerWithTeardown(element, event, handler) {
  element.addEventListener(event, handler);
  ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener(event, handler));
}

function getOperationsInfo(element, event, work, app) {
  const totalWorkLengthInPixels = element.clientWidth;
  const touchOffsetInPixels = event.clientX - element.offsetLeft;
  const totalParts = work.parts().length;
  const totalWorkLengthInAvus = work.parts().reduce((sum, currentPart) => sum + currentPart.length(), 0);
  const avusPerPixel = totalWorkLengthInAvus / totalWorkLengthInPixels;
  const touchOffsetInAvus = touchOffsetInPixels * avusPerPixel;
  const touchToleranceInAvus = TOUCH_TOLERANCE_IN_PIXELS * avusPerPixel;

  for (let currentPartIndex = 0, currentBorderOffsetInAvus = 0; currentPartIndex < totalParts; currentPartIndex += 1) {
    const currentPartLength = work.parts()[currentPartIndex].length();
    const leftBorderOffsetInAvus = currentBorderOffsetInAvus;
    const rightBorderOffsetInAvus = leftBorderOffsetInAvus + currentPartLength;
    const isTouchWithinCurrentPart = touchOffsetInAvus >= leftBorderOffsetInAvus && touchOffsetInAvus < rightBorderOffsetInAvus;
    if (isTouchWithinCurrentPart) {
      const info = {};
      info.isResizing = false;
      info.index = currentPartIndex;
      info.avusPerPixel = avusPerPixel;
      info.initialTouchOffsetInAvus = touchOffsetInAvus;
      info.touchOffsetWithinPartInAvus = touchOffsetInAvus - leftBorderOffsetInAvus;

      if (touchOffsetInAvus <= (leftBorderOffsetInAvus + touchToleranceInAvus) && currentPartIndex !== 0) {
        info.isResizing = app.currentTool() === 'default';
        info.leftIndex = currentPartIndex - 1;
        info.rightIndex = currentPartIndex;
        info.initalLeftPartLengthInAvus = work.parts()[currentPartIndex - 1].length();
        info.initalRightPartLengthInAvus = work.parts()[currentPartIndex].length();
      } else if (touchOffsetInAvus >= (rightBorderOffsetInAvus - touchToleranceInAvus) && currentPartIndex !== (totalParts - 1)) {
        info.isResizing = app.currentTool() === 'default';
        info.leftIndex = currentPartIndex;
        info.rightIndex = currentPartIndex + 1;
        info.initalLeftPartLengthInAvus = work.parts()[currentPartIndex].length();
        info.initalRightPartLengthInAvus = work.parts()[currentPartIndex + 1].length();
      }

      return info;
    }

    currentBorderOffsetInAvus = rightBorderOffsetInAvus;
  }

  return undefined;
}

function applyMovement(currentOperationsInfo, work, element) {
  if (!currentOperationsInfo || !currentOperationsInfo.isResizing) {
    return;
  }
  const minPartLengthInAvus = TOUCH_TOLERANCE_IN_PIXELS * currentOperationsInfo.avusPerPixel;
  const touchOffsetInPixels = event.clientX - element.offsetLeft;
  const touchOffsetInAvus = touchOffsetInPixels * currentOperationsInfo.avusPerPixel;
  const distanceInAvus = Math.round(touchOffsetInAvus - currentOperationsInfo.initialTouchOffsetInAvus);
  const newLeftPartLength = currentOperationsInfo.initalLeftPartLengthInAvus + distanceInAvus;
  const newRightPartLength = currentOperationsInfo.initalRightPartLengthInAvus - distanceInAvus;
  if (newLeftPartLength >= minPartLengthInAvus && newRightPartLength >= minPartLengthInAvus) {
    work.parts()[currentOperationsInfo.leftIndex].length(newLeftPartLength);
    work.parts()[currentOperationsInfo.rightIndex].length(newRightPartLength);
  }
}

function applyRelease(currentOperationsInfo, work, element, event, app) {
  if (!currentOperationsInfo || currentOperationsInfo.isResizing) {
    return;
  }
  const newInfo = getOperationsInfo(element, event, work, app);
  if (newInfo && !newInfo.isResizing && newInfo.index === currentOperationsInfo.index) {
    const clickedPart = work.parts()[newInfo.index];

    if (app.currentTool() === 'default') {
      app.currentPart(clickedPart);
    } else if (app.currentTool() === 'scissors') {
      splitPart(work, newInfo.index, newInfo.touchOffsetWithinPartInAvus);
      app.currentPart(work.parts()[newInfo.index + 1]);
    } else if (app.currentTool() === 'glue') {
      console.log('right or left is here the question!');
    }
    event.stopPropagation();
  }
}

function toggleResizeCursor(element, currentOperationsInfo) {
  if (currentOperationsInfo && currentOperationsInfo.isResizing) {
    element.classList.add('u-col-resize');
  } else {
    element.classList.remove('u-col-resize');
  }
}

function register() {
  ko.bindingHandlers.partOperations = {
    init: function (element, valueAccessor) {
      const app = valueAccessor().app;
      const work = valueAccessor().work;

      registerEventListenerWithTeardown(element, 'mousedown', onMouseDown);
      registerEventListenerWithTeardown(element, 'mouseup', onMouseUp);
      registerEventListenerWithTeardown(element, 'mouseleave', onMouseLeave);
      registerEventListenerWithTeardown(element, 'mousemove', onMouseMove);

      let currentOperationsInfo = undefined;

      function onMouseDown(event) {
        currentOperationsInfo = getOperationsInfo(element, event, work, app);
        toggleResizeCursor(element, currentOperationsInfo);
      }

      function onMouseUp(event) {
        applyRelease(currentOperationsInfo, work, element, event, app);
        currentOperationsInfo = undefined;
        toggleResizeCursor(element, undefined);
      }

      function onMouseLeave(event) {
        currentOperationsInfo = undefined;
        toggleResizeCursor(element, currentOperationsInfo);
      }

      function onMouseMove(event) {
        applyMovement(currentOperationsInfo, work, element);
        toggleResizeCursor(element, currentOperationsInfo || getOperationsInfo(element, event, work, app));
      }
    }
  };
}

////// TODO EXTRACT ///////////////////////////////

function splitPart(work, partIndex, splitPoint) {
  console.log('YAY');
  const oldPartsArray = work.parts();
  const partToSplit = oldPartsArray[partIndex];
  const originalLength = partToSplit.length();

  const leftClone = clonePart(partToSplit);
  const rightClone = clonePart(partToSplit);
  leftClone.length(splitPoint);
  rightClone.length(originalLength - splitPoint);

  const newPartsArray = [];
  oldPartsArray.slice(0, partIndex).forEach(x => newPartsArray.push(x));
  newPartsArray.push(leftClone);
  newPartsArray.push(rightClone);
  oldPartsArray.slice(partIndex + 1).forEach(x => newPartsArray.push(x));

  work.parts(newPartsArray);
}

function clonePart(part) {
  return {
    id: ko.observable(newId()),
    length: ko.observable(part.length()),
    color: ko.observable(part.color()),
    name: ko.observable(part.name())
  };
}

function newId() {
  return uuid.v4();
}

export default { register };
<|endoftext|>


<commit_before>import Component from '@ember/component';
import { sort, filterBy } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import { task, timeout } from 'ember-concurrency';

export default Component.extend({
  flashMessages: service(),
  sortedContestsProperties: [
    'num',
  ],
  sortedContestantsProperties: [
    'competitorTotPoints:desc',
  ],
  filteredChampionships: filterBy(
    'model.session.contests',
    'notQualifier',
  ),
  filteredContests: filterBy(
    'filteredChampionships',
    'status',
    'Included',
  ),
  filteredContestants: filterBy(
    'model.contest.contestants',
    'status',
    'Included',
  ),
  sortedOutcomes: sort(
    'model.round.outcomes',
    'sortedContestsProperties'
  ),
  sortedContestants: sort(
    'filteredContestants',
    'sortedContestantsProperties'
  ),
  autosave: task(function* (property){
    yield timeout(200);
    try {
      yield property.save();
    } catch(e) {
      e.errors.forEach((error) => {
        this.flashMessages.danger(error.detail);
      })
    }
  }).restartable(),
  actions: {
    saveModel(model){
      model.save();
      this.flashMessages.success("Saved!");
    },
  }
});
<commit_msg>Add saved flash on outcome save<commit_after>import Component from '@ember/component';
import { sort, filterBy } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import { task, timeout } from 'ember-concurrency';

export default Component.extend({
  flashMessages: service(),
  sortedContestsProperties: [
    'num',
  ],
  sortedContestantsProperties: [
    'competitorTotPoints:desc',
  ],
  filteredChampionships: filterBy(
    'model.session.contests',
    'notQualifier',
  ),
  filteredContests: filterBy(
    'filteredChampionships',
    'status',
    'Included',
  ),
  filteredContestants: filterBy(
    'model.contest.contestants',
    'status',
    'Included',
  ),
  sortedOutcomes: sort(
    'model.round.outcomes',
    'sortedContestsProperties'
  ),
  sortedContestants: sort(
    'filteredContestants',
    'sortedContestantsProperties'
  ),
  autosave: task(function* (property){
    yield timeout(200);
    try {
      yield property.save();
      this.flashMessages.success("Saved!");
    } catch(e) {
      e.errors.forEach((error) => {
        this.flashMessages.danger(error.detail);
      })
    }
  }).restartable(),
  actions: {
    saveModel(model){
      model.save();
      this.flashMessages.success("Saved!");
    },
  }
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import Analytics from '../mixins/analytics';

export default Ember.Component.extend(Analytics, {
    providerUrlRegex: {
        //'bioRxiv': '', doesnt currently have urls
        Cogprints: /cogprints/,
        OSF: /https?:\/\/((?!api).)*osf.io/, // Doesn't match api.osf urls
        PeerJ: /peerj/,
        arXiv: /arxivj/
    },
    didRender() {
        MathJax.Hub.Queue(['Typeset', MathJax.Hub, this.$()[0]]);  // jshint ignore:line
    },
    numMaxChars: 300,
    showBody: false,
    footerIcon: Ember.computed('showBody', function() {
        return this.get('showBody') ? 'caret-up' : 'caret-down';
    }),
    result: null,

    shortDescription: Ember.computed('result', function() {
        let result = this.get('result');
        if (result.description && result.description.length > this.numMaxChars) {
            return result.description.substring(0, this.numMaxChars) + '...';
        }
        return result.description.slice();
    }),

    osfID: Ember.computed('result', function() {
        let re = /osf.io\/(\w+)\/$/;
        let re2 = /osf.io\/preprints\/(\w+)\/$/;
        // NOTE / TODO : This will have to be removed later. Currently the only "true" preprints are solely from the OSF
        // socarxiv and the like sometimes get picked up by as part of OSF, which is technically true. This will prevent
        // broken links to things that aren't really preprints.
        if (this.get('result.providers.length') !== 1) {
            return false;
        }
        if (this.get('result.providers').find(provider => provider.name === 'OSF')) {
            for (let i = 0; i < this.get('result.identifiers.length'); i++)
                if (re.test(this.get('result.identifiers')[i]))
                    return re.exec(this.get('result.identifiers')[i])[1];
        } else {
            for (let i = 0; i < this.get('result.identifiers.length'); i++)
                if (re2.test(this.get('result.identifiers')[i]))
                    return re2.exec(this.get('result.identifiers')[i])[1];
        }
        return false;
    }),

    hyperlink: Ember.computed('result', function() {
        let re = null;
        for (let i = 0; i < this.get('result.providers.length'); i++)
            re = this.providerUrlRegex[this.get('result.providers')[i].name] || this.providerUrlRegex['OSF'];

        const identifiers = this.get('result.identifiers').filter(ident => ident.startsWith('http://'));

        for (let j = 0; j < identifiers.length; j++)
            if (re.test(identifiers[j]))
                return identifiers[j];

        return identifiers[0];
    }),

    actions: {
        toggleShowBody() {
            this.set('showBody', !this.showBody);

            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'result',
                    action: !this.showBody ? 'contract' : 'expand',
                    label: this.result.title
                });
        },
        select(item) {
            this.attrs.select(item);
        }
    }

});
<commit_msg>Go back to just using hyperlink<commit_after>import Ember from 'ember';
import Analytics from '../mixins/analytics';

export default Ember.Component.extend(Analytics, {
    providerUrlRegex: {
        //'bioRxiv': '', doesnt currently have urls
        Cogprints: /cogprints/,
        OSF: /https?:\/\/((?!api).)*osf.io/, // Doesn't match api.osf urls
        PeerJ: /peerj/,
        arXiv: /arxivj/
    },
    didRender() {
        MathJax.Hub.Queue(['Typeset', MathJax.Hub, this.$()[0]]);  // jshint ignore:line
    },
    numMaxChars: 300,
    showBody: false,
    footerIcon: Ember.computed('showBody', function() {
        return this.get('showBody') ? 'caret-up' : 'caret-down';
    }),
    result: null,

    shortDescription: Ember.computed('result', function() {
        let result = this.get('result');
        if (result.description && result.description.length > this.numMaxChars) {
            return result.description.substring(0, this.numMaxChars) + '...';
        }
        return result.description.slice();
    }),

    osfID: Ember.computed('result', function() {
        let re = /osf.io\/(\w+)\/$/;
        // NOTE / TODO : This will have to be removed later. Currently the only "true" preprints are solely from the OSF
        // socarxiv and the like sometimes get picked up by as part of OSF, which is technically true. This will prevent
        // broken links to things that aren't really preprints.
        if (this.get('result.providers.length') === 1 && this.get('result.providers').find(provider => provider.name === 'OSF'))
            for (let i = 0; i < this.get('result.identifiers.length'); i++)
                if (re.test(this.get('result.identifiers')[i]))
                    return re.exec(this.get('result.identifiers')[i])[1];
        return false;
    }),

    hyperlink: Ember.computed('result', function() {
        let re = null;
        for (let i = 0; i < this.get('result.providers.length'); i++)
            re = this.providerUrlRegex[this.get('result.providers')[i].name] || this.providerUrlRegex.OSF;

        const identifiers = this.get('result.identifiers').filter(ident => ident.startsWith('http://'));

        for (let j = 0; j < identifiers.length; j++)
            if (re.test(identifiers[j]))
                return identifiers[j];

        return identifiers[0];
    }),

    actions: {
        toggleShowBody() {
            this.set('showBody', !this.showBody);

            Ember.get(this, 'metrics')
                .trackEvent({
                    category: 'result',
                    action: !this.showBody ? 'contract' : 'expand',
                    label: this.result.title
                });
        },
        select(item) {
            this.attrs.select(item);
        }
    }

});
<|endoftext|>