Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

James lowenthal/134/replace dropdown with choices js #176

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading