diff --git a/src/index.html b/src/index.html
index 3817864..23b74d2 100644
--- a/src/index.html
+++ b/src/index.html
@@ -12,47 +12,6 @@
-
-
-
-
-
-
-
×
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/js/app.jsx b/src/js/app.jsx
index c76e31f..4bd29cb 100644
--- a/src/js/app.jsx
+++ b/src/js/app.jsx
@@ -22,24 +22,19 @@ class Application extends Component {
super(props);
this.toggleCheckbox = this.toggleCheckbox.bind(this);
this.state = {
+ query: '',
dates: [],
- filtered: {
- date: [],
- onscreen: [],
- searched: [],
- }
+ filteredByDate: [],
+ filteredByMap: [],
+ filteredByQuery: [],
};
this.allShows = [];
- this.onscreenShows = [];
this.popup = new mapboxgl.Popup({
closeButton: false,
});
- this.filterEl = document.getElementById('feature-filter');
- this.listingEl = document.getElementById('feature-listing');
-
this.bindMap = this.bindMap.bind(this);
this.start = {
@@ -101,20 +96,14 @@ class Application extends Component {
const checkedDates = _.filter(this.state.dates, _.matches({ checked: true }));
const checkedDatesList = _.map(checkedDates, 'date');
- // Filter
- this.state.filtered.date = this.allShows.filter(feature =>
- _.includes(checkedDatesList, feature.properties.date));
-
// Set filter for points
this.map.setFilter('shows', ['in', 'date'].concat(checkedDatesList));
// Update source, for clusters
this.map.getSource('shows').setData({
type: 'FeatureCollection',
- features: this.state.filtered.date,
+ features: this.state.filteredByDate,
});
-
- this.renderListings(this.map, this.state.filtered.date);
}
}
@@ -183,24 +172,24 @@ class Application extends Component {
const loadOnscreenShows = () => {
const bounds = map.getBounds();
- const features = geojson.features.filter(x =>
+ const features = this.state.filteredByDate.filter(x =>
inBounds(x.geometry.coordinates, bounds) &&
_.includes(getCheckedDatesList(), x.properties.date));
if (features) {
const uniqueFeatures = Util.getUniqueFeatures(features, 'bands');
// Populate features for the listing overlay.
- this.renderListings(map, uniqueFeatures);
-
- // Store the current features in sn `onscreenShows` variable to
- // later use for filtering on `keyup`.
- this.state.filtered.onscreen = uniqueFeatures;
+ this.setState({ filteredByMap: uniqueFeatures });
}
};
map.on('moveend', loadOnscreenShows);
+
// We are in 'load' listener already
+ this.setState({ filteredByDate: geojson.features });
loadOnscreenShows();
+ // Set state for first load
+
map.on('click', 'clusters', (e) => {
map.easeTo({
@@ -211,52 +200,11 @@ class Application extends Component {
map.on('click', 'shows', e => this.addPopupAndEase(map, e));
- this.filterEl.addEventListener('keyup', (e) => {
- const value = Util.normalize(e.target.value);
- // Unset filter if empty
- if (value === '') {
- showAllShows(geojson);
- }
-
- if (this.popup.getLngLat()) {
- this.popup.remove();
- }
-
- // Filter visible features that don't match the input value.
- const filtered = this.state.filtered.onscreen.filter((feature) => {
- const selected = _.includes(getCheckedDatesList(), feature.properties.date);
- const match = (x) => {
- const prop = Util.normalize(feature.properties[x]);
- return prop.indexOf(value) > -1 && selected;
- };
- return Object.keys(feature.properties).some(match);
- });
-
-
- // Populate the sidebar with filtered results
- this.renderListings(map, filtered);
-
- // Filter on source, for clusters
- map.getSource('shows').setData({
- type: 'FeatureCollection',
- features: filtered,
- });
-
- // Set the filter to populate features into the layer.
- const filteredShows = filtered.map(feature => feature.properties.sid);
- map.setFilter('shows', ['in', 'sid'].concat(filteredShows));
-
- this.state.filtered.searched = filtered;
- });
-
- // Call this function on initialization
- // passing an empty array to render an empty state
- this.renderListings(map, []);
$('#filter-all').on('click', () => {
// Util.toggleDates('all');
showAllShows(geojson);
- this.filterEl.value = '';
+ // this.filterEl.value = '';
$('.close-filter-modal').click();
});
@@ -301,11 +249,53 @@ class Application extends Component {
});
}
+
+ searchBarKeyup(e) {
+ const value = Util.normalize(e.target.value);
+ // Unset filter if empty
+ if (value === '') {
+ // showAllShows(geojson);
+ }
+
+ if (this.popup.getLngLat()) {
+ this.popup.remove();
+ }
+
+ // Filter visible features that don't match the input value.
+ const filtered = this.state.filteredByMap.filter((feature) => {
+ const match = (x) => {
+ const prop = Util.normalize(feature.properties[x]);
+ return prop.indexOf(value) > -1;
+ };
+ return Object.keys(feature.properties).some(match);
+ });
+
+
+ // Filter on source, for clusters
+ this.map.getSource('shows').setData({
+ type: 'FeatureCollection',
+ features: filtered,
+ });
+
+ // Set the filter to populate features into the layer.
+ const filteredShows = filtered.map(feature => feature.properties.sid);
+ this.map.setFilter('shows', ['in', 'sid'].concat(filteredShows));
+
+ this.setState({ filteredByQuery: filtered });
+ }
+
toggleCheckbox(date) {
const { dates } = this.state;
const idx = dates.findIndex((obj => obj.date === date));
dates[idx].checked = !dates[idx].checked;
- this.setState({ dates });
+
+ const checkedDates = _.filter(dates, _.matches({ checked: true }));
+ const checkedDatesList = _.map(checkedDates, 'date');
+
+ const filteredByDate = this.allShows.filter(feature =>
+ _.includes(checkedDatesList, feature.properties.date));
+
+ this.setState({ dates, filteredByDate });
}
addPopupAndEase(map, e) {
@@ -335,47 +325,83 @@ class Application extends Component {
this.mapContainer = el;
}
- renderListings(map, features) {
- // Clear any existing listings
- this.listingEl.innerHTML = '';
- if (features.length) {
- features.forEach((feature) => {
+ render() {
+ // Update the listings
+ const listings = [];
+ const { filteredByDate, filteredByMap } = this.state;
+ const intersection = _.intersection(filteredByDate, filteredByMap);
+ if (intersection.length) {
+ intersection.forEach((feature) => {
const prop = feature.properties;
- const item = document.createElement('p');
- item.textContent = prop.showString;
+ // add listener
const venue = `${prop.venue}
`;
- item.addEventListener('mouseover', () => {
+ const popupMouseOver = () => {
// Highlight corresponding feature on the map
this.popup.setLngLat(feature.geometry.coordinates)
.setHTML(venue + prop.showHTML)
- .addTo(map);
- });
-
- this.listingEl.appendChild(item);
+ .addTo(this.map);
+ };
+
+ const item = (
+
+ {prop.showString}
+
+ );
+ listings.push(item);
});
-
- // Show the filter input
- this.filterEl.parentNode.style.display = 'block';
} else {
- const empty = document.createElement('p');
- const text = this.filterEl.value === '' ? 'Drag the map to populate results' : 'No shows match criteria.';
- empty.textContent = text;
-
- this.listingEl.appendChild(empty);
-
- // Hide the filter input
- this.filterEl.parentNode.style.display = 'block';
-
- // remove features filter
- map.setFilter('shows', ['has', 'sid']);
+ const text = this.state.query === '' ? 'Drag the map to populate results' : 'No shows match criteria.';
+ listings.push({text}
);
}
- }
- render() {
return (
+
+
+
+
+
+
×
+
+
+
+
+
+
+
+
+
+
+ { listings }
+
+
);
}