<!DOCTYPE html>
<html lang="en">
  <head>
      <meta charset="utf-8">
      <title>Lab 7 - Ting copyright</title>

    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
           integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
           crossorigin=""/>

         <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
           integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
           crossorigin=""></script>

      <script src="https://code.jquery.com/jquery-3.3.1.min.js"
        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
        crossorigin="anonymous"></script>

        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
        integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
        crossorigin="anonymous"></script>

      <style>
          html, body { margin: 0; padding: 0; height: 100%; }
          #map { min-height: 100%; }
          
          
          
.legend, .temporal-legend {
   		padding: 6px 15px;
    	font: 14px/16px Arial, Helvetica, sans-serif;
   		background: white;
    	background: rgba(255,255,255,0.8);
    	box-shadow: 0 0 15px rgba(0,0,0,0.2);
    	border-radius: 5px;
	}
	#legendTitle {
  	  	text-align: center;
   	 	margin-bottom: 15px;
   		font-variant: small-caps;
	}
	.symbolsContainer {
    	float: left;
		margin-left: 50px;
	}
	.legendCircle {
     	border-radius:50%; 
     	border: 2px solid #501e65; 
     	background: rgba(80, 30, 101, .5);
	 	display: inline-block;
	}
	.legendValue {
    	position: absolute;
    	right: 8px;
	}
                               

      </style>
  </head>

  <body>
      <div id="map"></div>

      <script>
          var map = L.map('map', {
                center: [38.1625228, -96.9633171],
                zoom: 4
            });

         L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
           attribution: 'Map tiles by Carto, under CC BY 3.0. Data by OpenStreetMap, under ODbL.', //tl
           maxZoom: 11,
           minZoom: 4
         }).addTo(map);

          //change the file name to yours
            $.getJSON("city.geojson")  // The getJSON() method is used to get JSON data
            .done(function(data) {
                var info = processData(data);
                createPropSymbols(info.timestamps, data);
                createSliderUI(info.timestamps);
                 createLegend(info.min,info.max);
            });

          function processData(data) {
              // First, initialize the variables to hold the timestamps and min/max population values
              var timestamps = [];  // square brackets to define an array of data
                                    // because there are multiple timestamps
              var	min = Infinity; // for the min, begin with the largest possible value - infinity
              var	max = -Infinity;// for the max, begin with the smallest possible value - negative infinity

              // Go through each row/feature of the data table
              // Note data is the variable name in the function definition - processData(data)
              for (var feature in data.features) {
                  var properties = data.features[feature].properties;

                  // At each row, go through the columns/attributes to get the values
                  for (var attribute in properties) {
                      if ( attribute != 'id' &&
                           attribute != 'name' &&
                           attribute != 'latitude' &&
                           attribute != 'longitude' )   // != means NOT EQUAL TO
                                                  // These three columns are NOT recorded
                                                  // Modify this part when mapping your own data
                      {
                          if ( $.inArray(attribute,timestamps) ===  -1) { // JQuery in.Array() method searches for a specified value within an array and return its index (or -1 if not found)
                                                            // here, the new timestamp is only added when it is not already in the array
                                                            // triple equals === compares both type and value

                              timestamps.push(attribute);  // The JS push() method adds new items to the end of an array
                                                           // and returns the new length of the array
                          }
                          if (properties[attribute] < min) {
                              min = properties[attribute]; // record/update the current smaller values as the min
                          }
                          if (properties[attribute] > max) {
                              max = properties[attribute]; // record/update the current larger values as the max
                          }
                      }
                  }
              }
              return {
                  timestamps : timestamps,
                  min : min,
                  max : max
              }
            }

          // The function to draw the proportional symbols
            function createPropSymbols(timestamps, data) {

              cities = L.geoJson(data, {

                  // By default, Leaflet draws geojson points as simple markers
                  // To alter this, the pointToLayer function needs to be used
                  pointToLayer: function(feature, latlng) {
                      return L.circleMarker(latlng, { // we use circle marker for the points
                          fillColor: "#501e65",  // fill color of the circles
                          color: '#501e65',      // border color of the circles
                          weight: 2,             // circle line weight in pixels
                          fillOpacity: 0.5       // fill opacity (0-1)
                      }).on({
                          mouseover: function(e) {
                                this.openPopup();
                                this.setStyle({fillColor: 'green'});  // fill color turns green when mouseover
                            },
                            mouseout: function(e) {
                                this.closePopup();
                                this.setStyle({fillColor: '#501e65'});  // fill turns original color when mouseout
                            }
                    });
                  }
              }).addTo(map);

              updatePropSymbols(timestamps[0]); // this function is defined below
                                              // When loaded, the map will first show proportional symbols with the first timestamp's data
            }

            // The function to update/resize each circle marker according to a value in the time series
            function updatePropSymbols(timestamp) {

              cities.eachLayer(function(layer) {  // eachLayer() is an Leaflet function to iterate over the layers/points of the map

                  var props = layer.feature.properties;   // attributes
                  var radius = calcPropRadius(props[timestamp]); // circle radius, calculation function defined below

                  // pop-up information (when mouseover) for each city is also defined here
                  var popupContent = props.name + ' ' + timestamp + ' population: ' + String(props[timestamp]);

                  layer.setRadius(radius);  // Leaflet method for setting the radius of a circle
                  layer.bindPopup(popupContent, { offset: new L.Point(0,-radius) }); // bind the popup content, with an offset
              });
            }

            // calculate the radius of the proportional symbols based on area
            function calcPropRadius(attributeValue) {

              var scaleFactor = 0.001;   // the scale factor is used to scale the values; the units of the radius are in meters, tl
                                         // you may determine the scale factor accordingly based on the range of the values and the mapping scale
              var area = attributeValue * scaleFactor;

              return Math.sqrt(area/Math.PI);  // the function return the radius of the circle to be used in the updatePropSymbols()
            }

          function createSliderUI(timestamps) {

          var sliderControl = L.control({ position: 'bottomleft'} ); // position of the slider
                              // Another use of L.control :)

          sliderControl.onAdd = function(map) {
              var slider = L.DomUtil.create("input", "range-slider");
              L.DomEvent.addListener(slider, 'mousedown', function(e) {
                  L.DomEvent.stopPropagation(e);
              });

              $(slider)
                  .attr({'type':'range', 'max': timestamps[timestamps.length-1], 'min':timestamps[0], 'step': 10,'value': String(timestamps[0])})
                  .on('input change', function() {
                      updatePropSymbols($(this).val().toString()); // update the map with slider
                      $(".temporal-legend").text(this.value); // update the label with slider
                  });
              return slider;
          }

          sliderControl.addTo(map);
          createTimeLabel(timestamps[0]);
        }


        // add labels to the time slider
        function createTimeLabel(startTimestamp) {
          var temporalLegend = L.control({position: 'bottomleft' }); // same position as the slider
                               // One more use of L.control !!

          temporalLegend.onAdd = function(map) {
              var output = L.DomUtil.create("output", "temporal-legend");
              return output;
          }
          temporalLegend.addTo(map);
          $(".temporal-legend").text(startTimestamp); //display the first year by default
        }
          
              
function createLegend(min, max) {
		 
		if (min < 10) {	
			min = 10; 
		}

        		function roundNumber(inNumber) {

				return (Math.round(inNumber/10) * 10);  
		}
        
		var legend = L.control( { position: 'bottomright'} );

		legend.onAdd = function(map) {

		var legendContainer = L.DomUtil.create("div", "legend");  
		var symbolsContainer = L.DomUtil.create("div", "symbolsContainer");
		var classes = [roundNumber(min), roundNumber((max-min)/2), roundNumber(max)]; 
		var legendCircle;  
		var lastRadius = 0;
		var currentRadius;
		var margin;

		L.DomEvent.addListener(legendContainer, 'mousedown', function(e) { 
			L.DomEvent.stopPropagation(e); 
		});  

		$(legendContainer).append("<h2 id='legendTitle'>Total Population</h2>");
		
		for (var i = 0; i <= classes.length-1; i++) {  

			legendCircle = L.DomUtil.create("div", "legendCircle");  
			
			currentRadius = calcPropRadius(classes[i]);
			
			margin = -currentRadius - lastRadius - 5;

			$(legendCircle).attr("style", "width: " + currentRadius*2 + 
				"px; height: " + currentRadius*2 + 
				"px; margin-left: " + margin + "px" );				
			$(legendCircle).append("<span class='legendValue'>"+classes[i]+"</span>");

			$(symbolsContainer).append(legendCircle);

			lastRadius = currentRadius;

		}

		$(legendContainer).append(symbolsContainer); 

		return legendContainer; //tl

		};

		legend.addTo(map);  
}
                        

      </script>

  </body>
</html>