diff --git a/assets/js/main.js b/assets/js/main.js
index 735bf52..278ef73 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -1,178 +1,208 @@
-let isProcessingCSV = false;
-let isProcessingKML = false;
-
-const fetchMeetings = (query, callback, isCSV, isKML) => {
- const script = document.createElement("script");
- script.src = `${query}&callback=${callback.name}`;
- document.body.appendChild(script);
- isProcessingCSV = isCSV;
- isProcessingKML = isKML;
-};
-
-const handleMeetingsData = (meetings) => {
- if (isProcessingCSV) {
+class MeetingDataProcessor {
+ constructor() {
+ this.isProcessingCSV = false;
+ this.isProcessingKML = false;
+ }
+
+ // D ynamically load JSONP data
+ fetchMeetings(query, isCSV, isKML) {
+ return new Promise((resolve, reject) => {
+ const script = document.createElement("script");
+ const callbackName = `jsonpCallback_${Date.now()}`;
+
+ window[callbackName] = (data) => {
+ document.body.removeChild(script);
+ delete window[callbackName];
+ this.handleMeetingsData(data, isCSV, isKML);
+ resolve(data);
+ };
+
+ script.src = `${query}&callback=${callbackName}`;
+ script.onerror = () => reject(new Error("Script loading failed"));
+ document.body.appendChild(script);
+
+ this.isProcessingCSV = isCSV;
+ this.isProcessingKML = isKML;
+ });
+ }
+
+ // handle data once it's fetched
+ handleMeetingsData(meetings, isCSV, isKML) {
+ if (isCSV) {
+ this.exportCSV(meetings);
+ }
+ if (isKML) {
+ this.exportKML(meetings);
+ }
+ }
+
+ // CSV export functionality
+ exportCSV(meetings) {
const csvContent = `data:text/csv;charset=utf-8,${encodeURIComponent(
- convertToCSV(meetings)
+ this.constructor.convertToCSV(meetings)
)}`;
const downloadLink = document.getElementById("downloadLink");
downloadLink.href = csvContent;
downloadLink.style.display = "block";
}
- if (isProcessingKML) {
+ // KML export functionality
+ exportKML(meetings) {
const kmlContent = `data:text/xml;charset=utf-8,${encodeURIComponent(
- convertToKML(meetings)
+ this.convertToKML(meetings)
)}`;
const kmlDownloadLink = document.getElementById("kmlDownloadLink");
kmlDownloadLink.href = kmlContent;
kmlDownloadLink.style.display = "block";
}
-};
-
-const convertToCSV = (data) => {
- const csvRows = [];
- const keys = Object.keys(data[0]);
- // header row
- csvRows.push(keys.join(","));
-
- data.forEach((row) => {
- const values = keys.map((key) => {
- let value = row[key];
- if (typeof value === "string") {
- // Escape double quotes and wrap in double quotes if it contains a comma
- if (value.includes(",") || value.includes('"')) {
+ // Convert data to CSV
+ static convertToCSV(data) {
+ const csvRows = [];
+ const keys = Object.keys(data[0]);
+ csvRows.push(keys.join(","));
+
+ data.forEach((row) => {
+ const values = keys.map((key) => {
+ let value = row[key];
+ if (
+ typeof value === "string" &&
+ (value.includes(",") || value.includes('"'))
+ ) {
value = `"${value.replace(/"/g, '""')}"`;
}
- }
- return value;
+ return value;
+ });
+ csvRows.push(values.join(","));
});
- csvRows.push(values.join(","));
- });
-
- return csvRows.join("\n");
-};
+ return csvRows.join("\n");
+ }
-const convertToKML = (data) => {
- const kmlHeader = `
-
+ // Convert data to KML
+ convertToKML(data) {
+ let kmlContent = `
-
- `;
-
- const kmlFooter = `
+ `;
+
+ const placemarks = data
+ .map((meeting) => {
+ const name = meeting["meeting_name"].trim() || "NA Meeting";
+ const lng = parseFloat(meeting["longitude"]);
+ const lat = parseFloat(meeting["latitude"]);
+ if (!lng || !lat) return "";
+
+ const description = this.constructor.prepareSimpleLine(meeting);
+ const address = this.constructor.prepareSimpleLine(meeting, false);
+
+ return `
+ ${name}
+ ${address ? `${address}` : ""}
+ ${description ? `${description}` : ""}
+
+ ${lng},${lat}
+
+ `;
+ })
+ .join("\n");
+
+ kmlContent +=
+ placemarks +
+ `
`;
- const placemarks = data.map((meeting) => {
- const name = meeting["meeting_name"].trim() || "NA Meeting";
- const lng = parseFloat(meeting["longitude"]);
- const lat = parseFloat(meeting["latitude"]);
-
- if (lng || lat) {
- const description = prepareSimpleLine(meeting);
- const address = prepareSimpleLine(meeting, false);
-
- return (
- ` \n` +
- ` ${name}\n` +
- (address ? ` ${address}\n` : "") +
- (description
- ? ` ${description}\n`
- : "") +
- ` \n` +
- ` ${lng},${lat}\n` +
- ` \n` +
- ` \n`
- );
- }
- });
+ return kmlContent;
+ }
- return kmlHeader + placemarks.join("\n") + kmlFooter;
-};
+ // KML and CSV data preparation
+ static prepareSimpleLine(meeting, withDate = true) {
+ const getLocationInfo = () => {
+ const locationInfo = [];
+ const addInfo = (property) => {
+ if (property in meeting) {
+ const value = meeting[property].trim();
+ if (value) {
+ locationInfo.push(value);
+ }
+ }
+ };
+
+ addInfo("location_text");
+ addInfo("location_street");
+ addInfo("location_city_subsection");
+ addInfo("location_municipality");
+ addInfo("location_neighborhood");
+ addInfo("location_province");
+ addInfo("location_postal_code_1");
+ addInfo("location_nation");
+ addInfo("location_info");
+
+ return locationInfo.join(", ");
+ };
-const exportData = () => {
- const query = document.getElementById("query").value;
- if (!query.includes("/client_interface/jsonp")) {
- alert("Invalid BMLT query URL, must use jsonp endpoint.");
- return;
- }
- // Only support GetSearchResults for KML
- const isKML = query.includes("GetSearchResults");
- fetchMeetings(query, handleMeetingsData, true, isKML);
- if (isKML) {
- fetchMeetings(query, handleMeetingsData, true, true);
- }
-};
-
-const prepareSimpleLine = (meeting, withDate = true) => {
- const getLocationInfo = () => {
- const locationInfo = [];
- const addInfo = (property) => {
- if (property in meeting) {
- const value = meeting[property].trim();
- if (value) {
- locationInfo.push(value);
+ const getDateString = () => {
+ const weekday_strings = [
+ "All",
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday",
+ ];
+ const weekday = parseInt(meeting["weekday_tinyint"].trim());
+ const weekdayString = weekday_strings[weekday];
+
+ const startTime = `2000-01-01 ${meeting["start_time"]}`;
+ const time = new Date(startTime);
+
+ if (weekdayString && withDate) {
+ let dateString = weekdayString;
+
+ if (!isNaN(time)) {
+ dateString += `, ${time.toLocaleTimeString("en-US", {
+ hour: "numeric",
+ minute: "numeric",
+ hour12: true,
+ })}`;
}
+
+ return dateString;
}
+
+ return "";
};
- addInfo("location_text");
- addInfo("location_street");
- addInfo("location_city_subsection");
- addInfo("location_municipality");
- addInfo("location_neighborhood");
- addInfo("location_province");
- addInfo("location_postal_code_1");
- addInfo("location_nation");
- addInfo("location_info");
-
- return locationInfo.join(", ");
- };
-
- const getDateString = () => {
- const weekday_strings = [
- "All",
- "Sunday",
- "Monday",
- "Tuesday",
- "Wednesday",
- "Thursday",
- "Friday",
- "Saturday",
- ];
- const weekday = parseInt(meeting["weekday_tinyint"].trim());
- const weekdayString = weekday_strings[weekday];
-
- const startTime = `2000-01-01 ${meeting["start_time"]}`;
- const time = new Date(startTime);
-
- if (weekdayString && withDate) {
- let dateString = weekdayString;
-
- if (!isNaN(time)) {
- dateString += `, ${time.toLocaleTimeString("en-US", {
- hour: "numeric",
- minute: "numeric",
- hour12: true,
- })}`;
- }
+ const locationInfo = getLocationInfo();
+ const dateString = getDateString();
+ if (withDate && dateString && locationInfo) {
+ return `${dateString}, ${locationInfo}`;
+ } else if (dateString) {
return dateString;
+ } else {
+ return locationInfo;
}
+ }
- return "";
- };
-
- const locationInfo = getLocationInfo();
- const dateString = getDateString();
-
- if (withDate && dateString && locationInfo) {
- return `${dateString}, ${locationInfo}`;
- } else if (dateString) {
- return dateString;
- } else {
- return locationInfo;
+ // start the export process
+ exportData(query) {
+ if (!query.includes("/client_interface/jsonp")) {
+ alert("Invalid BMLT query URL, must use jsonp endpoint.");
+ return;
+ }
+ const isCSV = true;
+ const isKML = query.includes("GetSearchResults");
+ this.fetchMeetings(query, isCSV, isKML).catch((error) =>
+ console.error("Error fetching meetings:", error)
+ );
}
-};
+}
+
+function exportData() {
+ const query = document.getElementById("query").value;
+ const processor = new MeetingDataProcessor();
+ processor.exportData(query);
+}