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 theHTMLElementsFactory from '../core/uiLib/HTMLElementsFactory.js'; |
26 | import theTravelNotesData from '../data/TravelNotesData.js'; |
27 | import theConfig from '../data/Config.js'; |
28 | import theTranslator from '../core/uiLib/Translator.js'; |
29 | import theMapLayersCollection from '../data/MapLayersCollection.js'; |
30 | import theApiKeysManager from '../core/ApiKeysManager.js'; |
31 | import theHTMLSanitizer from '../core/htmlSanitizer/HTMLSanitizer.js'; |
32 | import PrintEL from './PrintEL.js'; |
33 | import AfterPrintEL from './AfterPrintEL.js'; |
34 | import { ZERO, TWO } from '../main/Constants.js'; |
35 | |
36 | import { |
37 | LeafletCircleMarker, |
38 | LeafletDivIcon, |
39 | LeafletMap, |
40 | LeafletMarker, |
41 | LeafletPolyline, |
42 | LeafletTileLayer |
43 | } from '../leaflet/LeafletImports.js'; |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | class PrintPageBuilder { |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | #printRouteMapOptions; |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | #route; |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | #printViews; |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | #printToolbar; |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | #printButton; |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | #cancelButton; |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | #viewsCounter; |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | #viewsDiv; |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | #routePolyline; |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | #printEL; |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | #afterPrintEL; |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | onAfterPrint ( ) { |
135 | |
136 | |
137 | this.#viewsDiv.forEach ( viewDiv => document.body.removeChild ( viewDiv ) ); |
138 | this.#viewsDiv.length = ZERO; |
139 | |
140 | |
141 | this.#printButton.removeEventListener ( 'click', this.#printEL, false ); |
142 | this.#cancelButton.removeEventListener ( 'click', this.#afterPrintEL, false ); |
143 | document.body.removeChild ( this.#printToolbar ); |
144 | |
145 | |
146 | const childrens = document.body.children; |
147 | for ( let counter = 0; counter < childrens.length; counter ++ ) { |
148 | childrens.item ( counter ).classList.remove ( 'TravelNotes-Hidden' ); |
149 | } |
150 | |
151 | |
152 | theTravelNotesData.map.invalidateSize ( false ); |
153 | |
154 | |
155 | document.title = |
156 | 'Travel & Notes' + |
157 | ( '' === theTravelNotesData.travel.name ? '' : ' - ' + theTravelNotesData.travel.name ); |
158 | |
159 | |
160 | window.removeEventListener ( 'afterprint', this.#afterPrintEL, true ); |
161 | this.#afterPrintEL = null; |
162 | this.#printEL = null; |
163 | } |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | #getMapLayer ( ) { |
170 | const mapLayer = theMapLayersCollection.getMapLayer ( theTravelNotesData.travel.layerName ); |
171 | const url = theApiKeysManager.getUrl ( mapLayer ); |
172 | const leafletLayer = |
173 | 'wmts' === mapLayer.service.toLowerCase ( ) |
174 | ? |
175 | new LeafletTileLayer ( url ) |
176 | : |
177 | new ( LeafletTileLayer.WMS ) ( url, mapLayer.wmsOptions ); |
178 | |
179 | leafletLayer.options.attribution = theHTMLSanitizer.sanitizeToHtmlString ( |
180 | ' © <a href="https://www.openstreetmap.org/copyright" target="_blank" ' + |
181 | 'title="OpenStreetMap contributors">OpenStreetMap contributors</a> ' + |
182 | mapLayer.attribution + |
183 | '| © <a href="https://github.com/wwwouaiebe" target="_blank" ' + |
184 | 'title="https://github.com/wwwouaiebe">Travel & Notes</a> ' |
185 | ).htmlString; |
186 | |
187 | return leafletLayer; |
188 | } |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | #getNotesMarkers ( ) { |
195 | const notesMarkers = []; |
196 | this.#route.notes.forEach ( |
197 | note => { |
198 | const icon = new LeafletDivIcon ( |
199 | { |
200 | iconSize : [ note.iconWidth, note.iconHeight ], |
201 | iconAnchor : [ note.iconWidth / TWO, note.iconHeight / TWO ], |
202 | popupAnchor : [ ZERO, -note.iconHeight / TWO ], |
203 | html : note.iconContent, |
204 | className : 'TravelNotes-Map-AllNotes ' |
205 | } |
206 | ); |
207 | |
208 | const marker = new LeafletMarker ( |
209 | note.iconLatLng, |
210 | { |
211 | |
212 | zIndexOffset : 100, |
213 | icon : icon, |
214 | draggable : true |
215 | } |
216 | ); |
217 | notesMarkers.push ( marker ); |
218 | } |
219 | ); |
220 | return notesMarkers; |
221 | } |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | #createViewOnPage ( printView ) { |
229 | |
230 | this.#viewsCounter ++; |
231 | const viewId = 'TravelNotes-RouteViewDiv' + this.#viewsCounter; |
232 | |
233 | |
234 | const viewDiv = document.createElement ( 'div' ); |
235 | viewDiv.className = 'TravelNotes-routeViewDiv'; |
236 | viewDiv.id = viewId; |
237 | document.body.appendChild ( viewDiv ); |
238 | this.#viewsDiv.push ( viewDiv ); |
239 | |
240 | |
241 | viewDiv.style.width = String ( this.#printRouteMapOptions.paperWidth ) + 'mm'; |
242 | viewDiv.style.height = String ( this.#printRouteMapOptions.paperHeight ) + 'mm'; |
243 | |
244 | |
245 | const layers = this.#printRouteMapOptions.printNotes ? this.#getNotesMarkers ( ) : []; |
246 | |
247 | |
248 | layers.push ( this.#getMapLayer ( ) ); |
249 | |
250 | |
251 | layers.push ( |
252 | new LeafletCircleMarker ( |
253 | [ printView.entryPoint.lat, printView.entryPoint.lng ], |
254 | theConfig.printRouteMap.entryPointMarker |
255 | ) |
256 | ); |
257 | layers.push ( |
258 | new LeafletCircleMarker ( |
259 | [ printView.exitPoint.lat, printView.exitPoint.lng ], |
260 | theConfig.printRouteMap.exitPointMarker |
261 | ) |
262 | ); |
263 | |
264 | |
265 | layers.push ( this.#routePolyline ); |
266 | |
267 | |
268 | new LeafletMap ( |
269 | viewId, |
270 | { |
271 | attributionControl : true, |
272 | zoomControl : false, |
273 | center : [ |
274 | ( printView.bottomLeft.lat + printView.upperRight.lat ) / TWO, |
275 | ( printView.bottomLeft.lng + printView.upperRight.lng ) / TWO |
276 | ], |
277 | zoom : this.#printRouteMapOptions.zoomFactor, |
278 | minZoom : this.#printRouteMapOptions.zoomFactor, |
279 | maxZoom : this.#printRouteMapOptions.zoomFactor, |
280 | layers : layers |
281 | } |
282 | ); |
283 | } |
284 | |
285 | |
286 | |
287 | |
288 | |
289 | #createToolbar ( ) { |
290 | |
291 | |
292 | this.#printToolbar = theHTMLElementsFactory.create ( |
293 | 'div', |
294 | { |
295 | id : 'TravelNotes-PrintToolbar' |
296 | }, |
297 | document.body |
298 | ); |
299 | |
300 | |
301 | this.#printButton = theHTMLElementsFactory.create ( |
302 | 'div', |
303 | { |
304 | className : 'TravelNotes-UI-Button', |
305 | title : theTranslator.getText ( 'PrintPageBuilder - Print' ), |
306 | textContent : '🖨️' |
307 | }, |
308 | this.#printToolbar |
309 | ); |
310 | this.#printButton.addEventListener ( 'click', this.#printEL, false ); |
311 | |
312 | |
313 | this.#cancelButton = theHTMLElementsFactory.create ( |
314 | 'div', |
315 | { |
316 | className : 'TravelNotes-UI-Button', |
317 | title : theTranslator.getText ( 'PrintPageBuilder - Cancel print' ), |
318 | textContent : '❌' |
319 | }, |
320 | this.#printToolbar |
321 | ); |
322 | this.#cancelButton.addEventListener ( 'click', this.#afterPrintEL, false ); |
323 | } |
324 | |
325 | |
326 | |
327 | |
328 | |
329 | |
330 | |
331 | |
332 | |
333 | constructor ( route, printViews, printRouteMapOptions ) { |
334 | |
335 | Object.freeze ( this ); |
336 | |
337 | |
338 | this.#route = route; |
339 | this.#printViews = printViews; |
340 | this.#printRouteMapOptions = printRouteMapOptions; |
341 | |
342 | this.#viewsCounter = ZERO; |
343 | this.#viewsDiv = []; |
344 | |
345 | |
346 | this.#printEL = new PrintEL ( ); |
347 | this.#afterPrintEL = new AfterPrintEL ( this ); |
348 | } |
349 | |
350 | |
351 | |
352 | |
353 | |
354 | preparePage ( ) { |
355 | if ( this.#printRouteMapOptions.firefoxBrowser ) { |
356 | document.body.classList.add ( 'TravelNotes-Maps-FirefoxBrowser' ); |
357 | } |
358 | else { |
359 | document.body.classList.remove ( 'TravelNotes-Maps-FirefoxBrowser' ); |
360 | } |
361 | |
362 | |
363 | |
364 | const childrens = document.body.children; |
365 | for ( let counter = 0; counter < childrens.length; counter ++ ) { |
366 | childrens.item ( counter ).classList.add ( 'TravelNotes-Hidden' ); |
367 | } |
368 | |
369 | |
370 | document.title = |
371 | '' === theTravelNotesData.travel.name |
372 | ? |
373 | 'maps' |
374 | : |
375 | theTravelNotesData.travel.name + ' - ' + this.#route.computedName + ' - maps'; |
376 | this.#createToolbar ( ); |
377 | |
378 | |
379 | window.addEventListener ( 'afterprint', this.#afterPrintEL, true ); |
380 | |
381 | |
382 | |
383 | const latLngs = []; |
384 | const pointsIterator = this.#route.itinerary.itineraryPoints.iterator; |
385 | while ( ! pointsIterator.done ) { |
386 | latLngs.push ( pointsIterator.value.latLng ); |
387 | } |
388 | |
389 | this.#routePolyline = new LeafletPolyline ( |
390 | latLngs, |
391 | { |
392 | color : this.#route.color, |
393 | weight : this.#route.width, |
394 | dashArray : this.#route.dashString |
395 | } |
396 | ); |
397 | |
398 | |
399 | this.#viewsCounter = ZERO; |
400 | this.#printViews.forEach ( printView => this.#createViewOnPage ( printView ) ); |
401 | } |
402 | } |
403 | |
404 | export default PrintPageBuilder; |
405 | |
406 | |
407 | |