Skip to content

Commit

Permalink
Switch dropdown component to choices.js (#176)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesLowenthal authored Feb 12, 2024
1 parent f16f448 commit fed1448
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 41 deletions.
7 changes: 6 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@
<span class="site-title">Parking Lot Map</span>
<fieldset id="city-dropdown">
<label for="city-choice">Select a city: </label>
<select name="city-choice" id="city-choice"></select>
<select
single
name="city-choice"
class="city-choice"
id="city-choice"
></select>
</fieldset>
</div>
<div class="header-icons">
Expand Down
51 changes: 51 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@parcel/resolver-glob": "^2.10.3",
"choices.js": "^10.2.0",
"leaflet": "~1.9.3"
},
"devDependencies": {
Expand Down
28 changes: 27 additions & 1 deletion src/css/_header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ header {
.header-about-icon {
margin-right: 0.75em;
}

margin-left: auto;
}

@media only screen and (min-width: 48em) {
Expand All @@ -39,14 +41,38 @@ header {
.site-title {
flex: 1;
}

#city-dropdown {
display: flex;
align-items: center;
gap: 0.7em;
height: 40px;
margin-bottom: 6px;
}
}

#city-dropdown label {
font-weight: normal;
}

#city-choice {
.choices__inner {
border: 2px solid rgba(0, 0, 0, 0.2);
border-radius: 10px;
color: black;
height: 40px;

@media only screen and (min-width: 20em) {
min-width: 20em;
}
}

.choices__item--selectable {
font-size: 14px;
height: 40px;
}

.choices__list--dropdown,
.choices__list[aria-expanded] {
z-index: 1001;
color: black;
}
24 changes: 24 additions & 0 deletions src/js/dropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Choices from "choices.js";
import "choices.js/public/assets/styles/choices.css";
import scoreCardsData from "../../data/score-cards.json";

export const DROPDOWN = new Choices("#city-choice", {
allowHTML: false,
itemSelectText: "Select",
searchEnabled: true,
});

const setUpDropdown = (initialCityId, fallBackCityId) => {
const cities = Object.entries(scoreCardsData).map(([id, { Name }]) => ({
value: id,
label: Name,
}));
DROPDOWN.setChoices(cities);
if (Object.keys(scoreCardsData).includes(initialCityId)) {
DROPDOWN.setChoiceByValue(initialCityId);
} else {
DROPDOWN.setChoiceByValue(fallBackCityId);
}
};

export default setUpDropdown;
20 changes: 3 additions & 17 deletions src/js/setUpSite.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import setUpIcons from "./fontAwesome";
import scoreCardsData from "../../data/score-cards.json";
import setUpAbout from "./about";
import setUpShareUrlClickListener from "./share";
import setUpDropdown, { DROPDOWN } from "./dropdown";

const parkingLots = import("../../data/parking-lots/*"); // eslint-disable-line

Expand Down Expand Up @@ -48,21 +49,6 @@ const STYLES = {
},
};

const addCitiesToToggle = (initialCityId, fallbackCityId) => {
const cityToggleElement = document.getElementById("city-choice");
let validInitialId = false;
Object.entries(scoreCardsData).forEach(([id, { Name }]) => {
if (id === initialCityId) {
validInitialId = true;
}
const option = document.createElement("option");
option.value = id;
option.textContent = Name;
cityToggleElement.appendChild(option);
});
cityToggleElement.value = validInitialId ? initialCityId : fallbackCityId;
};

/**
* Create the initial map object.
*
Expand Down Expand Up @@ -198,7 +184,7 @@ const setUpAutoScorecard = async (map, cities, parkingLayer) => {
}
});
if (centralCity) {
document.getElementById("city-choice").value = centralCity;
DROPDOWN.setChoiceByValue(centralCity);
setScorecard(centralCity, cities[centralCity]);
}
});
Expand Down Expand Up @@ -280,7 +266,7 @@ const setUpSite = async () => {
setUpIcons();

const initialCityId = extractCityIdFromUrl(window.location.href);
addCitiesToToggle(initialCityId, "atlanta-ga");
setUpDropdown(initialCityId, "atlanta-ga");
setUpAbout();

const map = createMap();
Expand Down
41 changes: 19 additions & 22 deletions tests/app/setUpSite.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,14 @@ test("every city is in the toggle", async ({ page }) => {
const data = JSON.parse(rawData);
const expectedCities = Object.values(data).map((scoreCard) => scoreCard.Name);

await page.goto("");

// Wait a second to make sure the site is fully loaded.
await page.waitForTimeout(1000);
await page.goto("/");
await page.waitForSelector(".choices");

const toggleValues = await page.evaluate(() => {
const select = document.querySelector("#city-choice");
return Array.from(select.querySelectorAll("option")).map((opt) =>
opt.textContent.trim()
);
});
const toggleValues = await page.$$eval(".choices__item--choice", (elements) =>
Array.from(elements.map((opt) => opt.textContent.trim()))
);

toggleValues.sort();
expectedCities.sort();
expect(toggleValues).toEqual(expectedCities);
});
Expand All @@ -47,11 +43,12 @@ test("correctly load the city score card", async ({ page }) => {
route.continue();
});

await page.goto("");
await page.goto("/");
expect(albanyLoaded).toBe(false);
await page.waitForSelector(".choices");

const selectElement = await page.$("#city-choice");
await selectElement.selectOption("albany-ny");
await page.click(".choices");
await page.click('.choices__item--choice >> text="Albany, NY"');
await page.waitForFunction(() => {
const titleElement = document.querySelector(
".leaflet-popup-content .title"
Expand Down Expand Up @@ -93,10 +90,8 @@ test.describe("the share feature", () => {
const context = await browser.newContext();
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
const page = await context.newPage();
await page.goto("");

// Wait a second to make sure the site is fully loaded.
await page.waitForTimeout(1000);
await page.goto("/");
await page.waitForSelector(".url-copy-button > a");

await page.click(".url-copy-button > a");
const firstCityClipboardText = await page.evaluate(() =>
Expand All @@ -106,8 +101,9 @@ test.describe("the share feature", () => {

// Check that the share button works when changing the city, too.
// This is a regression test.
const selectElement = await page.$("#city-choice");
await selectElement.selectOption("anchorage-ak");
await page.waitForSelector(".choices");
await page.click(".choices");
await page.click('.choices__item--choice >> text="Anchorage, AK"');
await page.waitForFunction(() => {
const titleElement = document.querySelector(
".leaflet-popup-content .title"
Expand All @@ -129,7 +125,7 @@ test.describe("the share feature", () => {
await page.goto("#parking-reform-map=fort-worth-tx");

// Wait a second to make sure the site is fully loaded.
await page.waitForTimeout(1000);
await page.waitForSelector(".leaflet-popup-content .title");

const [scoreCardTitle, cityToggleValue] = await page.evaluate(() => {
const title = document.querySelector(
Expand Down Expand Up @@ -234,8 +230,7 @@ test.describe("auto-focus city", () => {
test("scorecard pulls up city closest to center", async ({ page }) => {
await page.goto("");

// Wait a second to make sure the site is fully loaded.
await page.waitForTimeout(1000);
await page.waitForSelector(".leaflet-control-zoom-out");

// Zoom out.
await page
Expand All @@ -244,6 +239,8 @@ test("scorecard pulls up city closest to center", async ({ page }) => {

// Drag map to Birmingham
await dragMap(page, 300);

await page.waitForSelector(".choices");
const [scoreCardTitle, cityToggleValue] = await page.evaluate(() => {
const title = document.querySelector(
".leaflet-popup-content .title"
Expand Down

0 comments on commit fed1448

Please sign in to comment.