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
...