JSFiddle - React, Tailwind, and code Playground

by ajmeese7

HTML

<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/ol.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/control.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<div style="width: 96%; margin: 20px auto;">
	<div id="addressPickerContainer">
			<!-- this will populate programatically -->
			<div class="addressPickerTabColumn" ></div>
		
			<!-- map controls -->
			<div class="addressPickerMap">
				<div id="mapLock"></div>
				<div id="layoutImage"></div>
				<div class="mapBox">
					<div id="map" class="map"></div>	
				</div>
				
	</div>
	
	
	
</div>

<!-- svg controls the mask placed over the map and 'd' value changes based on appropriate svgpath -->
<svg height="0" width="0">
  <defs>
    <clipPath id="svgPath">
      <path fill="#FFFFFF" stroke="#000000" stroke-miterlimit="10" 
			 d="m 0 0 l 280 0 l 0 280 l -280 0 l 0 -280" />
    </clipPath>
  </defs>
</svg>
<!-- end invisible svg -->

CSS

#addressPickerContainer {
	width: 100%;
  width: 1000px;
  min-width: 500px;
}
.addressPickerTabColumn {
  width: calc(100% - 344px);
  padding-top: 5px;
  float: left;
}
.addressPickerTab {
  position: relative;
  height: 25px;
  border: 2px solid black;
  background-color: white;
  left: 1px;
  padding: 1px 5px;
  cursor: pointer;
  overflow: hidden;
  border-radius: 3px 0px 0px 3px;
  margin-top: 3px;
  background-color: #dadada;
}
.addressPickerTab.active {
  min-height: 70px;
  border-right: none;
  padding: 5px;
  background-color: #fff;
  overflow: visible;
}
.addressPickerTab input {
  margin-top: 5px;
  width: 94%;
  margin: 2px 3%;
}
.addressPickerTab>div {
  position: relative;
  top: -4px;
}
.addressPickerTab label {
  font-size: x-small;
  font-weight: 700;
  margin: 0;
  cursor: pointer;
}
.addressPickerTab>div>span {
  position: relative;
  top: 6px;
  font-size: 0.6em;
  float: right;
  color: red;
}
.addressPickerTab.active > div > span {
  /* color: orange; */
  top: 2px;
  right: 2px;
}
.addressPickerMap {
  border: 2px solid #000;
	height: 300px;
	width: 300px;
  float: left;
  margin-top: 3px;
  padding: 5px;
}


/********* CSS FOR AUTO COMPLETE ADDRESS ******/
.autocomplete-container {
  /*the container must be positioned relative:*/
  position: relative;
  margin-bottom: 20px;
  z-index: 1000;
}
.autocomplete-items {
  position: absolute;
  border: 1px solid rgba(0, 0, 0, 0.1);
  box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.1);
  border-top: none;
  z-index: 99;
  /*position the autocomplete items to be the same width as the container:*/
  top: calc(100% + 2px);
  left: 0;
  right: 0;

  background-color: #fff;
}
.autocomplete-items div {
  padding: 10px;
  cursor: pointer;
}
.autocomplete-items div:hover {
  /*when hovering an item:*/
  background-color: rgba(0, 0, 0, 0.1);
}
.autocomplete-items .autocomplete-active {
  /*when navigating through the items using the arrow keys:*/
  background-color: rgba(0, 0, 0, 0.1);
}
.clear-button {
 ...

JavaScript

/*jshint multistr: true */


/*these variables will come from previous user elections */
var numTabs = 4;

//populate based on number of maps
addressesContainer = document.getElementById('addressPickerContainer').getElementsByClassName('addressPickerTabColumn')[0];
for (i = 1; i <= numTabs; i++) {

  html = "<div id='MapTab" + i + "' class='addressPickerTab' onclick='clickTab(this)''>";
  html += "<div>";
  html += "<label>Addresss " + i + "</label><span>Incomplete</span>";
  html += "<div class='autocomplete-container' id='autocomplete-container" + i + "'></div>";
  html += "</div>";
  html += "</div>";
  html += "</div>";
  addressesContainer.innerHTML += html;
}

for (i = 1; i <= numTabs; i++) {

  addressAutocomplete(document.getElementById("autocomplete-container" + i), (data) => {
    if (data) {
      //THIS IS WHAT HAPPENS WHEN AN ADDRESS IS SELECTED
      console.log("map will eventually populate.");
      console.log("Lon: " + data.properties.lon, "Lat: " + data.properties.lat);

    } else {
      //THIS HAPPENS WHEN AN ITEM IS BEING CLEARED

    }

  }, {
    placeholder: "Enter an address for map " + i
  });

}





function clickTab(tab) {
  clickedTab = document.getElementById(tab.id);
  var tabNum = clickedTab.id.substring(clickedTab.id.indexOf("MapTab") + 6);
  currentMap = tabNum;

  if (clickedTab.classList.contains('active')) { //if the clicked tab is already active
    if (document.activeElement.classList[0] != "addressAutocompleteInput") { //if the active element isn't the autocomplete dropdown then minimize
      clickedTab.classList.remove("active");
      //clickedTab.nextElementSibling.classList.remove("active");
    }
  } else { //if the clicked tab is not currently active
    for (i = 0; i < clickedTab.parentElement.children.length; i++) { //close any tabs that are 'active'
      if (clickedTab.parentElement.children[i].classList.contains('active')) {
        // minimize the tab and hide the details
       ...