Skip to content

Commit

Permalink
Add search
Browse files Browse the repository at this point in the history
  • Loading branch information
FedorovAlexander committed Aug 5, 2024
1 parent b85df27 commit 8afeb12
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 26 deletions.
115 changes: 93 additions & 22 deletions src/routes/+page.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
#container {
&.empty {
display: flex;
flex-direction: column;
justify-content: center;
height: 80%;
}
}

#map {
position: absolute;
top: 0;
Expand All @@ -11,11 +20,11 @@
right: -300px;
width: 300px;
height: 100%;
background-color: #fff;
font-family: Arial, Helvetica, sans-serif;
overflow: hidden;
padding-bottom: 30px;
font-family: Arial, Helvetica, sans-serif;
background-color: #fff;
transition: right 0.3s ease-in-out;
overflow: hidden;
}

#sidebar.open {
Expand All @@ -28,19 +37,19 @@
}

.image-caption {
color: #111;
font-size: 12px;
font-style: italic;
margin: 0;
padding: 0 10px;
color: #111;
font-style: italic;
font-size: 12px;
}

.image-container {
display: flex;
flex-direction: column;
justify-content: center;
min-height: fit-content;
width: 100%;
min-height: fit-content;
margin: 0;
}

Expand All @@ -49,34 +58,36 @@
overflow: auto;
}

.close {
.close-button {
position: absolute;
top: 0;
right: 0;
width: 24px;
height: 24px;
margin: 3px;
padding: 0;
color: lightgray !important;
border: none;
background-color: transparent;
cursor: pointer;
background-color: transparent;
}

.close-icon {
width: 24px;
height: 24px;
}

.title {
color: #111;
font-size: 20px;
margin: 10px 0 5px;
padding: 10px;
color: #111;
font-size: 20px;
}

.date,
.description,
.link {
color: #111;
font-size: 14px;
margin: 10px 0;
padding: 10px;
color: #111;
font-size: 14px;
}

.description {
Expand All @@ -90,41 +101,101 @@
}

.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
border: 16px solid #f3f3f3;
border-top: 16px solid #3498db;
border-radius: 50%;
animation: spin 1s ease-in infinite;
}

.loader-container {
z-index: 100;
position: absolute;
top: calc(50% - 60px);
left: calc(50% - 60px);
z-index: 100;
}

.search {
z-index: 11;
position: absolute;
top: 0;
left: 0;
box-sizing: border-box;
width: 100%;
max-width: 400px;
padding: 10px;
}

.search__input-field {
box-sizing: border-box;
width: 100%;
height: 40px;
padding: 5px;
padding: 0 10px;
border: none;
border-radius: 8px;
}

.search__dropdown-list {
box-sizing: border-box;
width: 100%;
max-height: 50vh;
margin: 2px 0 0;
padding: 0;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #fff;
transition: all 0.3s ease-in-out;
overflow: hidden;
overflow: auto;
}

.search__dropdown-button {
width: 100%;
padding: 10px;
border: none;
text-align: left;
cursor: pointer;
background: transparent;
transition: background-color 0.3s ease-in-out;
}

.search__dropdown-button:hover {
background-color: #f3f3f3;
}

.search__dropdown-button:active {
background-color: #e3e3e3;
}

@keyframes spin {
0% {
transform: rotate(0deg);
}

100% {
transform: rotate(360deg);
}
}

@media screen and (max-width: 700px) and (min-width: 600px) {
.search {
max-width: 300px;
}
}

@media only screen and (max-width: 600px) {
#sidebar {
top: auto;
right: 0;
left: 0;
bottom: calc(-45% - 30px);
left: 0;
width: 100%;
height: 45%;
transition: bottom 0.3s ease-in-out;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
transition: bottom 0.3s ease-in-out;
}

#sidebar.open {
Expand Down
93 changes: 89 additions & 4 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
features: [],
};
let dropdownItems = [];
onMount(async () => {
mapboxgl.accessToken = MAPBOX_CONFIG.accessToken;
Expand All @@ -49,8 +51,9 @@
center: MAPBOX_CONFIG.initialCenter,
zoom: MAPBOX_CONFIG.initialZoom,
});
map.addControl(new mapboxgl.NavigationControl(), 'top-left');
if (!mobile) {
map.addControl(new mapboxgl.NavigationControl(), MAPBOX_CONFIG.navigationControlPosition);
}
}
async function processBattleData(battles) {
Expand Down Expand Up @@ -242,6 +245,67 @@
link: '',
};
}
function searchBattlesByTitle(event) {
dropdownItems = battlesGeoJson.features.filter((battle) => {
return battle.properties.title.toLowerCase().includes(event.target.value.toLowerCase());
});
}
function onSelectDropdownItem(event) {
const battleTitle = event.target.innerText;
const index = battlesGeoJson.features.findIndex((battle) => battle.properties.title === battleTitle);
const coordinates = battlesGeoJson.features[index].geometry.coordinates;
map.easeTo({
center: coordinates,
padding: {
bottom: mobile ? window.innerHeight / 2 : 0,
top: 0,
left: 0,
right: mobile ? 0 : (window.innerWidth - 150) / 2,
},
zoom: 10,
});
currentBattle = extractBattleData(battlesGeoJson.features[index].properties);
dropdownItems = [];
openSidebar = true;
}
function handleDropdownItemKeyEvent(event) {
const currentIndex = parseInt(event.target.parentElement.dataset.index);
let nextIndex, nextItem;
switch (event.key) {
case 'Enter':
onSelectDropdownItem(event);
break;
case 'Escape':
dropdownItems = [];
break;
case 'ArrowDown':
nextIndex = currentIndex + 1;
nextItem = document.querySelector(`[data-index="${nextIndex}"]`);
if (nextItem) {
nextItem.querySelector('button').focus();
}
break;
case 'ArrowUp':
nextIndex = currentIndex - 1;
nextItem = document.querySelector(`[data-index="${nextIndex}"]`);
if (nextItem) {
nextItem.querySelector('button').focus();
}
break;
default:
break;
}
}
</script>
{#if loading}
Expand All @@ -250,11 +314,27 @@
</div>
{/if}
<section id="map"></section>
{#if !loading}
<div class="search">
<input class="search__input-field" type="text" placeholder="Search for a battle" on:keyup={searchBattlesByTitle} />
{#if dropdownItems.length > 0}
<ul class="search__dropdown-list">
{#each dropdownItems as { properties }, i}
<li class="search__dropdown-item" data-index={i}>
<button class="search__dropdown-button" on:click={onSelectDropdownItem} on:keyup={handleDropdownItemKeyEvent}>
{properties.title}
</button>
</li>
{/each}
</ul>
{/if}
</div>
{/if}
<aside id="sidebar" class:open={openSidebar}>
<header>
<button class="close" on:click={closeSidebar} aria-label="Close sidebar">
<img src={closeIcon} alt="Close sidebar" class="close" />
<button class="close-button" on:click={closeSidebar} aria-label="Close sidebar">
<img class="close-icon" src={closeIcon} alt="Close sidebar" />
</button>
</header>
<article class="sidebar-content">
Expand All @@ -278,6 +358,11 @@
{/if}
{#if currentBattle.description}
<p class="description">{currentBattle.description}</p>
{:else}
<p class="description">No description available</p>
{/if}
{#if currentBattle.casualties}
<p class="casualties">Casualties: {currentBattle.casualties}</p>
{/if}
</article>
</aside>
Expand Down
1 change: 1 addition & 0 deletions src/utils/mapboxConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const MAPBOX_CONFIG = {
textSize: 12,
pointCircleRadius: 8,
pointCircleStrokeWidth: 2,
navigationControlPosition: 'bottom-left',
};

export default MAPBOX_CONFIG;

0 comments on commit 8afeb12

Please sign in to comment.