1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | import ObjId from '../data/ObjId.js'; |
26 | import SvgProfileBuilder from '../core/lib/SvgProfileBuilder.js'; |
27 | import theHTMLElementsFactory from '../core/uiLib/HTMLElementsFactory.js'; |
28 | import theHTMLSanitizer from '../core/htmlSanitizer/HTMLSanitizer.js'; |
29 | import theTranslator from '../core/uiLib/Translator.js'; |
30 | import theUtilities from '../core/uiLib/Utilities.js'; |
31 | import theNoteHTMLViewsFactory from '../viewsFactories/NoteHTMLViewsFactory.js'; |
32 | import theTravelNotesData from '../data/TravelNotesData.js'; |
33 | |
34 | import { ZERO, DISTANCE, ICON_DIMENSIONS } from '../main/Constants.js'; |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | class RouteHTMLViewsFactory { |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | #getManeuverHTML ( classPrefix, routeAndManeuver ) { |
54 | const maneuverHTML = theHTMLElementsFactory.create ( 'div' ); |
55 | const maneuverIconHTML = theHTMLElementsFactory.create ( |
56 | 'div', |
57 | { |
58 | className : |
59 | classPrefix + 'Route-ManeuversAndNotes-IconCell' |
60 | }, |
61 | maneuverHTML |
62 | ); |
63 | |
64 | theHTMLElementsFactory.create ( |
65 | 'div', |
66 | { |
67 | className : |
68 | 'TravelNotes-ManeuverNote TravelNotes-ManeuverNote-' + |
69 | routeAndManeuver.maneuver.iconName |
70 | }, |
71 | maneuverIconHTML |
72 | ); |
73 | |
74 | maneuverIconHTML.dataset.tanWidth = String ( ICON_DIMENSIONS.width ) + 'px'; |
75 | maneuverIconHTML.dataset.tanHeight = String ( ICON_DIMENSIONS.height ) + 'px'; |
76 | |
77 | const maneuverTextHTML = theHTMLElementsFactory.create ( |
78 | 'div', |
79 | { |
80 | className : classPrefix + 'Route-ManeuversAndNotes-Cell' |
81 | }, |
82 | maneuverHTML |
83 | ); |
84 | |
85 | theHTMLElementsFactory.create ( |
86 | 'div', |
87 | { |
88 | className : classPrefix + 'Route-Maneuver-TooltipContent', |
89 | textContent : theTranslator.getText ( 'RouteHTMLViewsFactory - ' + routeAndManeuver.maneuver.iconName ) |
90 | }, |
91 | maneuverTextHTML |
92 | ); |
93 | |
94 | theHTMLSanitizer.sanitizeToHtmlElement ( |
95 | routeAndManeuver.maneuver.instruction, |
96 | theHTMLElementsFactory.create ( |
97 | 'div', |
98 | { |
99 | className : classPrefix + 'Route-Maneuver-Instruction' |
100 | }, |
101 | maneuverTextHTML |
102 | ) |
103 | ); |
104 | |
105 | if ( routeAndManeuver.route.chain ) { |
106 | theHTMLSanitizer.sanitizeToHtmlElement ( |
107 | '<span>' + |
108 | theTranslator.getText ( 'RouteHTMLViewsFactory - Distance from start of travel' ) + |
109 | '</span>\u00a0:\u00a0' + |
110 | theUtilities.formatDistance ( routeAndManeuver.route.chainedDistance + routeAndManeuver.maneuverDistance ), |
111 | theHTMLElementsFactory.create ( |
112 | 'div', |
113 | { |
114 | className : classPrefix + 'Route-Maneuver-TravelDistance' |
115 | }, |
116 | maneuverTextHTML |
117 | ) |
118 | ); |
119 | } |
120 | |
121 | theHTMLSanitizer.sanitizeToHtmlElement ( |
122 | '<span>' + |
123 | theTranslator.getText ( 'RouteHTMLViewsFactory - Distance from start of route' ) + |
124 | '</span>\u00a0:\u00a0' + |
125 | theUtilities.formatDistance ( routeAndManeuver.maneuverDistance ), |
126 | theHTMLElementsFactory.create ( |
127 | 'div', |
128 | { |
129 | className : classPrefix + 'Route-Maneuver-RouteDistance' |
130 | }, |
131 | maneuverTextHTML |
132 | ) |
133 | ); |
134 | |
135 | if ( DISTANCE.defaultValue < routeAndManeuver.maneuver.distance ) { |
136 | theHTMLSanitizer.sanitizeToHtmlElement ( |
137 | '<span>' + |
138 | theTranslator.getText ( 'RouteHTMLViewsFactory - Next maneuver after' ) + |
139 | '</span>\u00a0:\u00a0' + |
140 | theUtilities.formatDistance ( routeAndManeuver.maneuver.distance ), |
141 | theHTMLElementsFactory.create ( |
142 | 'div', |
143 | { |
144 | className : classPrefix + 'Route-Maneuver-NextDistance' |
145 | }, |
146 | maneuverTextHTML |
147 | ) |
148 | ); |
149 | } |
150 | return maneuverHTML; |
151 | } |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | constructor ( ) { |
158 | Object.freeze ( this ); |
159 | } |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | getRouteProfileHTML ( classPrefix, route ) { |
168 | const profileDiv = theHTMLElementsFactory.create ( 'div', { className : classPrefix + 'RouteProfile' } ); |
169 | theHTMLSanitizer.sanitizeToHtmlElement ( theTranslator.getText ( 'RouteHTMLViewsFactory - Profile' ), profileDiv ); |
170 | profileDiv.appendChild ( new SvgProfileBuilder ( ).createSvg ( route ) ); |
171 | |
172 | return profileDiv; |
173 | } |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | getRouteManeuversAndNotesHTML ( classPrefix, route, addDataset ) { |
185 | const notesAndManeuvers = []; |
186 | const notesIterator = route.notes.iterator; |
187 | while ( ! notesIterator.done ) { |
188 | notesAndManeuvers.push ( |
189 | { |
190 | data : notesIterator.value, |
191 | distance : notesIterator.value.distance |
192 | } |
193 | ); |
194 | } |
195 | const maneuversIterator = route.itinerary.maneuvers.iterator; |
196 | let maneuverDistance = ZERO; |
197 | while ( ! maneuversIterator.done ) { |
198 | notesAndManeuvers.push ( |
199 | { |
200 | data : maneuversIterator.value, |
201 | distance : maneuverDistance |
202 | } |
203 | ); |
204 | maneuverDistance += maneuversIterator.value.distance; |
205 | } |
206 | notesAndManeuvers.sort ( ( first, second ) => first.distance - second.distance ); |
207 | const routeNotesAndManeuversHTML = theHTMLElementsFactory.create ( |
208 | 'div', |
209 | { |
210 | className : classPrefix + 'Route-ManeuversAndNotes' |
211 | } |
212 | ); |
213 | notesAndManeuvers.forEach ( |
214 | noteOrManeuver => { |
215 | let noteOrManeuverHTML = null; |
216 | if ( 'Note' === noteOrManeuver.data.objType.name ) { |
217 | noteOrManeuverHTML = theNoteHTMLViewsFactory.getNoteTextAndIconHTML ( |
218 | classPrefix, |
219 | { note : noteOrManeuver.data, route : route } |
220 | ); |
221 | noteOrManeuverHTML.className = classPrefix + 'Route-Notes-Row'; |
222 | } |
223 | else { |
224 | noteOrManeuverHTML = this.#getManeuverHTML ( |
225 | classPrefix, |
226 | { |
227 | route : route, |
228 | maneuver : noteOrManeuver.data, |
229 | maneuverDistance : noteOrManeuver.distance |
230 | } |
231 | ); |
232 | noteOrManeuverHTML.className = classPrefix + 'Route-Maneuvers-Row'; |
233 | } |
234 | if ( addDataset ) { |
235 | noteOrManeuverHTML.dataset.tanObjId = noteOrManeuver.data.objId; |
236 | noteOrManeuverHTML.dataset.tanMarkerObjId = ObjId.nextObjId; |
237 | noteOrManeuverHTML.dataset.tanObjType = noteOrManeuver.data.objType.name; |
238 | } |
239 | routeNotesAndManeuversHTML.appendChild ( noteOrManeuverHTML ); |
240 | } |
241 | ); |
242 | |
243 | return routeNotesAndManeuversHTML; |
244 | } |
245 | |
246 | |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | |
254 | getRouteHeaderHTML ( classPrefix, route ) { |
255 | const routeHeaderHTML = theHTMLElementsFactory.create ( |
256 | 'div', |
257 | { |
258 | className : classPrefix + 'Route-Header', |
259 | id : 'route' + route.objId |
260 | } |
261 | ); |
262 | |
263 | theHTMLSanitizer.sanitizeToHtmlElement ( |
264 | route.computedName, |
265 | theHTMLElementsFactory.create ( |
266 | 'div', |
267 | { |
268 | className : classPrefix + 'Route-Header-Name' |
269 | }, |
270 | routeHeaderHTML |
271 | ) |
272 | ); |
273 | |
274 | if ( ZERO !== route.distance ) { |
275 | theHTMLSanitizer.sanitizeToHtmlElement ( |
276 | '<span>' + |
277 | theTranslator.getText ( 'RouteHTMLViewsFactory - Route distance' ) + |
278 | '</span>\u00a0:\u00a0' + |
279 | theUtilities.formatDistance ( route.distance ), |
280 | theHTMLElementsFactory.create ( |
281 | 'div', |
282 | { |
283 | className : classPrefix + 'Route-Header-Distance' |
284 | }, |
285 | routeHeaderHTML |
286 | ) |
287 | ); |
288 | } |
289 | |
290 | if ( ! theTravelNotesData.travel.readOnly && 'bike' !== route.itinerary.transitMode ) { |
291 | theHTMLSanitizer.sanitizeToHtmlElement ( |
292 | '<span>' + |
293 | theTranslator.getText ( 'RouteHTMLViewsFactory - Duration' ) + |
294 | '</span>\u00a0:\u00a0' + |
295 | theUtilities.formatTime ( route.duration ), |
296 | theHTMLElementsFactory.create ( |
297 | 'div', |
298 | { |
299 | className : classPrefix + 'Route-Header-Duration' |
300 | }, |
301 | routeHeaderHTML |
302 | ) |
303 | ); |
304 | } |
305 | |
306 | if ( route.itinerary.hasProfile ) { |
307 | theHTMLSanitizer.sanitizeToHtmlElement ( |
308 | '<span>' + |
309 | theTranslator.getText ( 'RouteHTMLViewsFactory - Ascent' ) + |
310 | '</span>\u00a0:\u00a0' + |
311 | String ( route.itinerary.ascent.toFixed ( ZERO ) ) + |
312 | ' m.', |
313 | theHTMLElementsFactory.create ( |
314 | 'div', |
315 | { |
316 | className : classPrefix + 'Route-Header-Ascent' |
317 | }, |
318 | routeHeaderHTML |
319 | ) |
320 | ); |
321 | theHTMLSanitizer.sanitizeToHtmlElement ( |
322 | '<span>' + |
323 | theTranslator.getText ( 'RouteHTMLViewsFactory - Descent' ) + |
324 | '</span>\u00a0:\u00a0' + |
325 | String ( route.itinerary.descent.toFixed ( ZERO ) ) + |
326 | ' m.', |
327 | theHTMLElementsFactory.create ( |
328 | 'div', |
329 | { |
330 | className : classPrefix + 'Route-Header-Descent' |
331 | }, |
332 | routeHeaderHTML |
333 | ) |
334 | ); |
335 | } |
336 | return routeHeaderHTML; |
337 | } |
338 | |
339 | |
340 | |
341 | |
342 | |
343 | |
344 | |
345 | |
346 | getRouteFooterHTML ( classPrefix, route ) { |
347 | let footerText = |
348 | ( ( '' !== route.itinerary.provider ) && ( '' !== route.itinerary.transitMode ) ) |
349 | ? |
350 | theTranslator.getText ( |
351 | 'RouteHTMLViewsFactory - Itinerary computed by {provider} and optimized for {transitMode}', |
352 | { |
353 | provider : route.itinerary.provider, |
354 | transitMode : theTranslator.getText ( |
355 | 'RouteHTMLViewsFactory - TransitMode ' + route.itinerary.transitMode |
356 | ) |
357 | } |
358 | ) |
359 | : |
360 | ''; |
361 | |
362 | const footerHTML = theHTMLElementsFactory.create ( 'div', { className : classPrefix + 'RouteFooter' } ); |
363 | |
364 | theHTMLSanitizer.sanitizeToHtmlElement ( footerText, footerHTML ); |
365 | |
366 | return footerHTML; |
367 | } |
368 | |
369 | } |
370 | |
371 | |
372 | |
373 | |
374 | |
375 | |
376 | |
377 | |
378 | const theRouteHTMLViewsFactory = new RouteHTMLViewsFactory ( ); |
379 | |
380 | export default theRouteHTMLViewsFactory; |
381 | |
382 | |
383 | |