1/** 2 * This file defines a generalized way to add and remove overlays to elements. 3 * Provides specific functions for handling no data in remote files and spinners 4 * but can also be used in a generalized sense. 5 */ 6(function (mapsUtil) { 7 "use strict"; 8 9 (function main() { 10 exportConfig(); 11 })(); 12 13 /** 14 * Draw the missing data message on the map. 15 * @param {Element} elem - A HTML element within the map structure. Generally keyed by .interactive-map. 16 * @param {Metadata} metadata - Metadata for the map. 17 */ 18 function addFileNoDataOverlay(elem, metadata) { 19 const map = mapsUtil.findMap(elem); 20 map.append(buildMapOverlayNoData(metadata)); 21 } 22 23 /** 24 * Adds the spinner overlay. 25 * @param {Element} elem - A HTML element within the map structure. Generally keyed by .interactive-map. 26 * @param {Metadata} metadata - The maps metadata. Needed for layer key. 27 */ 28 function addSpinnerOverlay(elem, metadata) { 29 const map = mapsUtil.findMap(elem); 30 map.activeLayer = metadata.layer; // for clearOverlaySpinnerLoaded 31 const overlay = buildMapOverlaySpinner(); 32 map.append(overlay); 33 } 34 35 /** 36 * Clears the missing data overlay. 37 * @param {Element} elem - A HTML element within the map structure. Generally keyed by .interactive-map. 38 */ 39 function clearOverlayNoData(elem) { 40 clearOverlayByClassName(elem, ".map-overlay-no-data"); 41 } 42 43 /** 44 * Clears the spinner overlay. 45 * @param {Element} elem - A HTML element within the map structure. Generally keyed by .interactive-map. 46 */ 47 function clearOverlaySpinner(elem) { 48 clearOverlayByClassName(elem, ".map-overlay-spinner"); 49 } 50 51 /** 52 * Clears the spinner overlay, if the main map layer has loaded. 53 * @param {Element} elem - A HTML element within the map structure. Generally keyed by .interactive-map. 54 * @param {Metadata} metadata - The maps metadata. Needed for layer key. 55 */ 56 function clearOverlaySpinnerLoaded(elem, metadata) { 57 const map = mapsUtil.findMap(elem); 58 if (map.activeLayer === metadata.layer) { 59 clearOverlaySpinner(elem); 60 } 61 } 62 63 /** 64 * Clears an overlay, if it exists. 65 * @param {Element} elem - A HTML element within the map structure. Generally keyed by .interactive-map. 66 * @param {string} className - Class selector of overlay to remove. Generally map-overlay-spinner or 67 * map-overlay-no-data. 68 */ 69 function clearOverlayByClassName(elem, className) { 70 const map = mapsUtil.findMap(elem); 71 const overlay = map.querySelector(className); 72 if (overlay) { 73 map.removeChild(overlay); 74 } 75 } 76 77 /** 78 * Builds the HTML for an overlay when data is loading. 79 * @return {HTMLDivElement} - The complete HTML element. 80 */ 81 function buildMapOverlaySpinner() { 82 const overlay = buildMapOverlay(); 83 overlay.classList.add("map-overlay-spinner"); 84 const spinner = document.createElement("div"); 85 spinner.className = "spinner spinner--centered icon-size--extra-large"; 86 overlay.append(spinner); 87 return overlay; 88 } 89 90 /** 91 * Builds the HTML for an overlay when the data is missing. 92 * @param {Metadata} metadata - The metadata for a map. Needed for the missing-text property. 93 * @return {HTMLDivElement} - The complete HTML element. 94 */ 95 function buildMapOverlayNoData(metadata) { 96 const overlay = buildMapOverlay(); 97 overlay.classList.add("map-overlay-no-data"); 98 const text = metadata["missing-text"] || "There is currently no information to display"; 99 const innerContent = document.createElement("span"); 100 innerContent.style.textShadow = "2px 2px 2px #fff"; 101 innerContent.textContent = text; 102 overlay.append(innerContent); 103 return overlay; 104 } 105 106 /** 107 * Builds the generic overlay which content will go into. 108 * @return {HTMLDivElement} - The wrapper HTML element. Extended by other invocations to add text/spinner. 109 */ 110 function buildMapOverlay() { 111 const overlay = document.createElement("div"); 112 overlay.className = "map-overlay z-100 position-absolute width-full height-full top-0 left-0 display-flex flex-align-center flex-justify-center padding-4 font-body-lg text-bold text-align-center"; 113 overlay.style.background = "rgba(216, 216, 216, .3)"; 114 return overlay; 115 } 116 117 /** 118 * Entry point to handle remote file having no data for OpenLayers maps 119 *. 120 * Draws overlay on top of map indicating the file has no data in it. 121 * @param {ol.source.Vector} source - Vector source of the main data layer. 122 * @param {Element} elem - Should be used to find the map wrapper for DOM manipulation 123 * @param {Metadata} metadata - Metadata for active tab. 124 */ 125 function handleOLSourceNoData(source, elem, metadata) { 126 const url = metadata.layer; 127 if (!url || checkOLSourceForNoData(url, source) === false) { 128 source.set("showNoDataOverlay", false); 129 return; 130 } 131 source.set("showNoDataOverlay", true); 132 addFileNoDataOverlay(elem, metadata); 133 } 134 135 /** 136 * Checks to see if a vector source has any data in it. 137 * 138 * Current known conditions for the file not having data are there being no features, there being exactly 1 feature 139 * with no geometry, on the fire-wx[1|2] layers there being exactly one feature, and on the fireoutlook-day[1|2] 140 * layers there being exactly 2 layers which both have a RISK parameters of -1. 141 * @param {string} url - URL of layer, needed for one-off fire conditions 142 * @param {ol.source.Vector} source - Vector source of the main data layer. 143 * @return {boolean} - true if the missing data overlay should be drawn. 144 */ 145 function checkOLSourceForNoData(url, source) { 146 const features = source.getFeatures(); 147 if (!features || features.length === 0) { 148 return true; 149 } 150 if (features.length === 1 && !features[0].getGeometry()) { 151 return true; 152 } 153 if (url.includes("firewx-day1") && features.length === 1 && _featureRiskMissing(features[0])) { 154 return true; 155 } 156 if (url.includes("fireoutlook-day") && features.length === 1 && _featureRiskMissing(features[0])) { 157 return true; 158 } 159 return ( 160 url.includes("fireoutlook-day") && 161 features.length === 2 && 162 _featureRiskMissing(features[0]) && 163 _featureRiskMissing(features[1]) 164 ); 165 } 166 167 /** 168 * Entry point to handle remote file having no data. Currently only w
168orks for geojson/json files. 169 * Draws overlay on top of map indicating the file has no data in it. 170 * 171 * @param {Element} elem - Should be used to find the map wrapper for DOM manipulation 172 * @param {Metadata} metadata Metadata for active tab. 173 * @param {{}} data - Pre-fetched data of layer. Either topojson or geojson. 174 */ 175 function handleFileNoData(elem, metadata, data) { 176 const url = metadata.layer; 177 if (!url) { 178 return; 179 } 180 if (mapsUtil.getExtension(url) !== "json" && mapsUtil.getExtension(url) !== "geojson") { 181 return; 182 } 183 if (checkJsonForNoData(url, data) === false) { 184 return; 185 } 186 addFileNoDataOverlay(elem, metadata); 187 } 188 189 /** 190 * Checks to see if a geojson or json file has any data in it. Current known conditions for the file not having data 191 * are there being no features, there being exactly 1 feature with no geometry, on the fire-wx[1|2] layers there 192 * being exactly one feature, and on the on the fireoutlook-day[1|2] layers there being exactly 2 layers which both 193 * have a RISK parameters of -1. 194 * 195 * @param {string} url - URL of layer, needed for one off fire conditions 196 * @param {{}} data - GeoJSON of layer. 197 * @return {boolean} - true if the file is missing and geometry. 198 */ 199 function checkJsonForNoData(url, data) { 200 if (!data) { 201 return true; 202 } 203 const features = data.features; 204 if (!features || features.length === 0) { 205 return true; 206 } 207 if (features.length === 1 && !features[0].geometry) { 208 return true; 209 } 210 if (url.indexOf("firewx-day1") !== -1 && features.length === 1 && _featureRiskMissing(features[0])) { 211 return true; 212 } 213 if (url.indexOf("fireoutlook-day") !== -1 && features.length === 1 && _featureRiskMissing(features[0])) { 214 return true; 215 } 216 if ( 217 url.includes("fireoutlook-day") && 218 features.length === 2 && 219 _featureRiskMissing(features[0]) && 220 _featureRiskMissing(features[1]) 221 ) { 222 return true; 223 } 224 return false; 225 } 226 227 /** 228 * Checks if a feature on a fire wx/outlook layer has a RISK value which indicates there's no data. 229 * 230 * Handles both openlayers features and text parsed from topojson for d3. 231 * @param {ol.Feature|{}} feature - Feature to check. 232 * @return {boolean} - true if the map should render the missing data overlay. 233 */ 234 function _featureRiskMissing(feature) { 235 if (feature.get && typeof feature.get === "function" && feature.get("RISK") === "-1") { 236 return true; 237 } 238 return ( 239 feature.hasOwnProperty("properties") && 240 feature.properties.hasOwnProperty("RISK") && 241 feature.properties.RISK === "-1" 242 ); 243 } 244 245 /** 246 * Exports functions to window.overlay. 247 */ 248 function exportConfig() { 249 window.overlay = { 250 addFileNoDataOverlay, 251 clearOverlayNoData, 252 clearOverlaySpinner, 253 clearOverlaySpinnerLoaded, 254 clearOverlayByClassName, 255 buildMapOverlaySpinner, 256 buildMapOverlayNoData, 257 buildMapOverlay, 258 addSpinnerOverlay, 259 handleFileNoData, 260 handleOLSourceNoData, 261 }; 262 } 263})(window.mapsUtil);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.