1 import { InfoSection
} from './infoSection.js';
3 class InfoPanel
extends HTMLElement
{
7 <div id='infoPanelContainer'>
8 <button id='infoButton' class='feature-controller'>
9 <svg class='svgIcon interactive-button'>
10 <use href="#info_black_24dp"></use>
13 <div id='infoPanel' class='feature-controller'>
14 <div id='closeInfoPanel' class='interactive-button close-panel'>x</div>
15 <h2>Feature List and Components</h2>
22 const infoButton
= this.querySelector('#infoButton');
23 const infoPanel
= this.querySelector('#infoPanel');
24 const closePanel
= this.querySelector('#closeInfoPanel');
25 L
.DomEvent
.disableClickPropagation(infoButton
);
26 L
.DomEvent
.disableClickPropagation(infoPanel
);
28 infoButton
.onclick
= () => {
29 if (infoPanel
.classList
.contains('clicked')) {
30 infoPanel
.classList
.remove('clicked');
32 infoPanel
.classList
.add('clicked');
35 closePanel
.onclick
= () => {
36 infoPanel
.classList
.remove('clicked');
39 this.addSubsections(infoPanel
);
42 addSubsections(infoPanel
) {
43 this.addCatalogMenuSection(infoPanel
);
44 this.addLayerControllerSection(infoPanel
);
45 this.addDomainSelectorSection(infoPanel
);
46 this.addSimulationControllerSection(infoPanel
);
47 this.addTimeSeriesSection(infoPanel
);
48 this.addURLSection(infoPanel
);
51 async
addCatalogMenuSection(infoPanel
) {
52 let header
= 'Catalog Menu';
53 let subsections
= ['Sorting Catalog', 'Searching Catalog'];
54 let catalogMenuSection
= await
new InfoSection(header
, subsections
);
55 infoPanel
.appendChild(catalogMenuSection
);
57 let generalDescription
= `The <i>Catalog Menu</i> shows all available simulations that can
58 be shown on the current account.
60 To access the menu click the <b>Catalog</b> button in the
61 top left of the screen`;
62 catalogMenuSection
.updateDescription(header
, generalDescription
);
64 let sortingDescription
= `The <i>Catalog Menu</i> can be sorted by the following categories using the <b>sort by</b> dropdown menu:
67 <b>orignal order</b>: order simulations were added to the server EXCEPT FOR simulations in the <b>Fuel moisture</b> column, which in
68 <i>original order</i> sorting are sorted by description.
71 <b>description</b>: sorted by alphabetical order of the simulation description (the text in bold of each simulation in the menu)
74 <b>start date</b>: sorted by earliest start date (labeled <i>from</i>) to latest
77 <b>end date</b>: sorted by earliest end date (labeled <i>to</i>) to latest
80 Order of any sorting can also be reversed using the <b>Reverse Order</b> checkbox
82 catalogMenuSection
.updateDescription(subsections
[0], sortingDescription
);
84 let searchingDescription
= `The <i>Catalog Menu</i> can be searched by the categories it is sorted by. For example, when <b>original order</b>
85 is selected, typing text in the search box will filter the results of every column based on if the description
86 of each simulation matches the text in the search box. Typing text in the search box when <b>start date</b> is
87 selected will filter based on whether start date matches the text. Search results can also be reversed. Search
88 results are cleared when the sorting category is changed.`;
89 catalogMenuSection
.updateDescription(subsections
[1], searchingDescription
);
92 async
addLayerControllerSection(infoPanel
) {
93 let header
= 'Layer Controller';
94 let subsections
= ['Layer Selection', 'Switching Domains', 'Top Layer Opacity', 'Timeseries over all Markers'];
95 let layerControllerSection
= await
new InfoSection(header
, subsections
);
96 infoPanel
.appendChild(layerControllerSection
);
98 let generalDescription
= `The <i>Layer Controller</i> is found on the right hand side of the screen after a simulation has
99 been selected from the <i>Catalog Menu</i> or can be accessed by clicking the <b>layer</b> button
100 at the top of the screen in mobile. It shows the different layers that can be shown in the
101 current simulation and domain.`;
102 layerControllerSection
.updateDescription(header
, generalDescription
);
104 let layerSelection
= `Selecting a layer from the <i>Layer Controller</i> adds it to the map and centers the map on the layer.
105 The layer may also show a colorbar that will appear on the left hand side of the screen. Adding a
106 layer will load the layer over the entire simulation (or a specified range of the simulation). The
107 <i>Simulation Controller</i> shows the progress of loading the simulation. Multiple
108 layers can be added at once, with the most recently added layer considered the 'top' layer. Clicking
109 an added layer in the <i>Layer Controller</i> removes that layer. If the 'top' layer is removed, the most
110 recently added layer before that layer becomes the new 'top' layer. The colorbar shown is always the
111 most recently added layer that has a colorbar.`
112 layerControllerSection
.updateDescription(subsections
[0], layerSelection
);
114 let switchDomains
= `When switching domains, all the currently added layers will be preserved if those layers exist in the
115 new domain. If they do not, the layer will be removed and will have to be re added if needed when returning
116 to the original domain.`
117 layerControllerSection
.updateDescription(subsections
[1], switchDomains
);
119 let opacityDescription
= `The opacity of the top layer can be changed using the <b>Top Layer Opacity</b> slider bar. Opacity values
120 range from 0 to 1 and change in increments of .05. To adjust the value the seeker can be clicked and dragged
121 to a new location, or the bar can be clicked directly to set the seeker to that location. Opacity is preserved
122 when switching domains always applies to the top most layer. If the top most layer is removed, the opacity will
123 apply to the new top most layer.`;
124 layerControllerSection
.updateDescription(subsections
[2], opacityDescription
);
126 let timeSeriesDescription
= `If there are any timeseries markers set, a timeseries can be created from the <i>Layer Controller</i> that draws
127 the data from all markers on the same chart. The date range is specified in the <b>start time</b> and
128 <b>end time</b> dropdown menus. If the dates selected from these menus extends beyond the <b>start date</b>
129 and <b>end date</b> of the simulation specified in the <i>Simulation Controller</i>, these values will be updated
130 and the corresponding data will be loaded.`;
131 layerControllerSection
.updateDescription(subsections
[3], timeSeriesDescription
);
134 async
addTimeSeriesSection(infoPanel
) {
135 let header
= 'Time Series Generation';
136 let subsections
= ['TimeSeries Markers', 'TimeSeries Chart', 'Data Type', 'Changing Domains'];
137 let timeSeriesSection
= await
new InfoSection(header
, subsections
);
138 infoPanel
.appendChild(timeSeriesSection
);
140 let generalDescription
= `If any added layers from the <i>Layer Controller</i> have an associated colorbar, a timeseries can be created to show
141 the values of any point in the layer as defined by the colorbar. The timeseries will always be associated with the top
142 most layer that has a colorbar.`;
143 timeSeriesSection
.updateDescription(header
, generalDescription
);
145 let markerDesc
= `Double clicking on a point in the top most layer with a colorbar will create a marker that shows some information about that point
146 including the latitude and longitude of the point on the map, the RGB values of the color at that point coded in that color, the
147 location in the colorbar of the point, and some options to create a timeSeries over a range of time at this point. Changing the value
148 of the current timestamp in the location using the <i>Simulation Controller</i> will also update the values in the marker accordingly
149 to match the update to the layer. Clicking the <b>generate timeseries</b> button will load all timestamps between the specified range
150 and retrieve the values in the colorbar at each time at the specified marker location and show a chart plotting these points. Selecting
151 <b>generate timeseries</b> from the marker will plot only the values at that marker's location. Multiple markers can be added to the layer
152 by double clicking at multiple locations and the timeseries associated with each marker can all be plotted with on the same chart by clicking
153 the <b>generate timeseries</b> button from the <b>Timeseries over all Markers</b> section of the <i>Layer Controller</i>.`;
154 timeSeriesSection
.updateDescription(subsections
[0], markerDesc
);
156 let chartDesc
= `After <b>generate timeseries</b> has been clicked, a chart will show in the center of the screen after all timestamps in the selected range
157 have been loaded and the values at the specified locations determined. When a timeseries is generated, the values at the corresponding locations
158 are cached for each timestamp so time spent reloading in the future is minimized. The generated chart can be clicked and dragged from the button in the top-left corner
159 to relocate the chart on the screen and the chart can be closed by clicking the <b>x</b> in the top-right corner. The color of the plotted line of values is determined by the color
160 of corresponding point on the layer at the time of generation. Clicking and dragging from top-left to bottom-right create a box that can be used
161 to zoom into specific locations on the chart. A zoom range can also be specified using the <b>zoom in start</b> and <b>zoom in end</b> dropdown
162 menus. After zooming, the chart can be returned to its original range by clicking the back arrow at the top-left corner of the chart. Clicking on a
163 specific point in the plot will move the current timestamp of the simulation to the timestamp corresponding to the clicked data point. Using the
164 <b>y-axis threshold</b> input box, a number value can be entered to draw a horizontal line on the chart at the value specified. All points above
165 this line will be highlighted, and all points below will be colored grey. This line can be given a label with the <b>threshold label</b> input.`;
166 timeSeriesSection
.updateDescription(subsections
[1], chartDesc
);
168 let dataTypeDesc
= `Changing the <b>data type</b> from the options used to create the timeseries Chart changes how the chart handles timestamps
169 that do not have any data associated with them in the layer a timeseries is being generated for.
172 Selecting <b>continuous</b> from the dropdown will ensure that every timestamp in the specified range has a value associated with it
173 in the generated timeseries. If the layer has no value at a specified location and timestamp, then zero will be filled at that timestamp.
176 Selecting <b>discrete</b> from the dropdown will not enforce every timestamp in the specified range having a value associated with it. The
177 generated timeseries will instead directly connect only timestamps that have values at the specified location in the layer.`;
178 timeSeriesSection
.updateDescription(subsections
[2], dataTypeDesc
);
180 let domainDesc
= `Changing domains will clear all timeSeries Markers. Returning to a domain will not return the cleared timeSeries Markers.`;
181 timeSeriesSection
.updateDescription(subsections
[3], domainDesc
);
184 async
addSimulationControllerSection(infoPanel
) {
185 let header
= 'Simulation Controller';
186 let subsections
= ['Basic Navigation', 'Simulation Start and Stop Times', 'Loading Progress', 'Domain Switching'];
187 let simulationControllerSection
= await
new InfoSection(header
, subsections
);
188 infoPanel
.appendChild(simulationControllerSection
);
190 let generalDescription
= `The <i>Simulation Controller</i> is found in the bottom left of the screen after a simulation
191 has been selected from the <i>Catalog Menu</i>. It shows the current timestamp in the simulation
192 as well as a bar showing the relative location of the current timestamp in full simulation.
193 The <i>Simulation Controller</i> is used to start and stop the simulation, navigate to a specific time,
194 and control whether the full simulation is loaded, or only subset of the simulation is loaded.`;
195 simulationControllerSection
.updateDescription(header
, generalDescription
);
197 let navDesc
= `Pressing Play will begin playing the simulation and advancing the timestamp. Pressing
198 the outer double arrows toggle speeding up or slowing down the simulation.
199 From a paused position, clicking either of the inner arrows either advances
200 the simulation by a single timestamp or goes back to the previous timestamp.
201 From the last timestamp of the simulation, advancing returns to the start, and
202 from the first timestamp, going back goes to the last timestamp of the simulation.
203 Users can also click the bar below the navigation buttons to navigate to a relative
204 location in the simulation. Alternatively the seeker showing the relative location in
205 the simulation can be clicked and dragged to a new location.`;
206 simulationControllerSection
.updateDescription(subsections
[0], navDesc
);
208 let startStopDesc
= `On the left and right ends of the navigation bar are two black bars that represent
209 start and stop times of the simulation. Selecting a layer from the <i>Layer Controller</i>
210 will load the layer over all timestamps included within the start and stop times specifid
211 with these two bars. Hovering over the bars will bring up a label specifying their exact
212 times and clicking and dragging the bars will reset them to a new time. The start time is
213 not permitted to exceed the end time and the current timestamp is not permitted to fall
214 outside the range of the start and end times. If while moving either the start or end times,
215 the range is updated such that the current timestamp is outside of it, the current timestamp
216 will update with whichever of the start or end times are updating.`;
217 simulationControllerSection
.updateDescription(subsections
[1], startStopDesc
);
219 let loadProgDesc
= `After a layer from the <i>Layer Controller</i> is selected, all timestamps within the start and
220 stop times will be loaded. The progress of loading will be shown on the navigation bar as a loading
221 bar starting at the start time and extending towards the end time. Once the loading bar has reached
222 the end time, all timestamps to play the simulation smoothly have been loaded. The simulation can still
223 be played while timestamps are still loading, but it may not be as smooth. The loading bar also only shows
224 the progress of the total times that need to be loaded and the location of the loading bar does not give
225 information about which times have been loaded. When loading begins, it starts at the current timestamp and
226 loads the times between the current timestamp and the end time chromatically first before chromatically loading the times
227 between the start time and the current timestamp. Layers that are loaded are cached so they do not need to
228 be reloaded if they are removed and then re-added.`;
229 simulationControllerSection
.updateDescription(subsections
[2], loadProgDesc
);
231 let domainDesc
= `When switching domains, if the new domain has not been loaded before, loading will begin on the selected
232 layers. The current timestamp, start time, and end time of the simulation are preserved when switching
233 domains UNLESS they do not exist in the new domain. If so than they will be updated to the nearest corresponding
234 timestamps in the new domain.`;
235 simulationControllerSection
.updateDescription(subsections
[3], domainDesc
);
238 async
addDomainSelectorSection(infoPanel
) {
239 let header
= 'Domain Selector';
240 let subsections
= [];
241 let domainSelectorSection
= await
new InfoSection(header
, subsections
);
242 infoPanel
.appendChild(domainSelectorSection
);
244 let generalDescription
= `The <i>Domain Selector</i> can be found underneath the <b>Catalog</b> button on desktop and by clicking
245 the <b>domains</b> button at the top of the screen on mobile. Switching between domains can change the size
246 and center of layers on the map as well as the granularity of the timestamps in the simulation (for example
247 going from hour increments in <i>domain 1</i> to 30 min increments in <i>domain 2</i>). Switching domains may
248 also change which layers are available to add to the map from the <i>Layer Controller</i>.`;
249 domainSelectorSection
.updateDescription(header
, generalDescription
);
252 async
addURLSection(infoPanel
) {
253 let header
= 'URL Navigation';
254 let subsections
= [];
255 let URLSection
= await
new InfoSection(header
, subsections
);
256 infoPanel
.appendChild(URLSection
);
258 let generalDescription
= `As various settings such as timestamp, added layers, domain, etc are
259 updated in the simulation they are saved as parameters in the URL.
260 Clicking <b>Copy Link to Clipboard</b> copies this URL that can be used
261 to navigate to the simulation preset to the state it was in when the URL
262 was copied. The URL can also be directly copied.`;
263 URLSection
.updateDescription(header
, generalDescription
);
267 window
.customElements
.define('info-panel', InfoPanel
);