| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  | import {InputElement} from "../InputElement"; | 
					
						
							|  |  |  | import {OpeningHour} from "../../../Logic/OpeningHours"; | 
					
						
							|  |  |  | import {UIEventSource} from "../../../Logic/UIEventSource"; | 
					
						
							|  |  |  | import {Utils} from "../../../Utils"; | 
					
						
							|  |  |  | import {UIElement} from "../../UIElement"; | 
					
						
							| 
									
										
										
										
											2020-10-06 02:09:09 +02:00
										 |  |  | import Translations from "../../i18n/Translations"; | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  | import {Browser} from "leaflet"; | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * This is the base-table which is selectable by hovering over it. | 
					
						
							|  |  |  |  * It will genarate the currently selected opening hour. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-10-06 01:37:02 +02:00
										 |  |  | export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]> { | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |     public readonly IsSelected: UIEventSource<boolean>; | 
					
						
							|  |  |  |     private readonly weekdays: UIEventSource<UIElement[]>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 02:09:09 +02:00
										 |  |  |     public static readonly days: UIElement[] = | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             Translations.t.general.weekdays.abbreviations.monday, | 
					
						
							|  |  |  |             Translations.t.general.weekdays.abbreviations.tuesday, | 
					
						
							|  |  |  |             Translations.t.general.weekdays.abbreviations.wednesday, | 
					
						
							|  |  |  |             Translations.t.general.weekdays.abbreviations.thursday, | 
					
						
							|  |  |  |             Translations.t.general.weekdays.abbreviations.friday, | 
					
						
							|  |  |  |             Translations.t.general.weekdays.abbreviations.saturday, | 
					
						
							|  |  |  |             Translations.t.general.weekdays.abbreviations.sunday | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 01:37:02 +02:00
										 |  |  |     private readonly source: UIEventSource<OpeningHour[]>; | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 01:37:02 +02:00
										 |  |  |     constructor(weekdays: UIEventSource<UIElement[]>, source?: UIEventSource<OpeningHour[]>) { | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |         super(weekdays); | 
					
						
							|  |  |  |         this.weekdays = weekdays; | 
					
						
							| 
									
										
										
										
											2020-10-06 01:37:02 +02:00
										 |  |  |         this.source = source ?? new UIEventSource<OpeningHour[]>([]); | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |         this.IsSelected = new UIEventSource<boolean>(false); | 
					
						
							|  |  |  |         this.SetStyle("width:100%;height:100%;display:block;"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InnerRender(): string { | 
					
						
							|  |  |  |         let rows = ""; | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         for (let h = 0; h < 24; h++) { | 
					
						
							|  |  |  |             let hs = "" + h; | 
					
						
							|  |  |  |             if (hs.length == 1) { | 
					
						
							|  |  |  |                 hs = "0" + hs; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             rows += `<tr><td rowspan="2" class="oh-left-col oh-timecell-full">${hs}:00</td>` + | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  |                 Utils.Times(weekday => `<td id="${this.id}-timecell-${weekday}-${h}" class="oh-timecell oh-timecell-full oh-timecell-${weekday}"></td>`, 7) + | 
					
						
							|  |  |  |                 '</tr><tr>' + | 
					
						
							|  |  |  |                 Utils.Times(id => `<td id="${this.id}-timecell-${id}-${h}-30" class="oh-timecell oh-timecell-half oh-timecell-${id}"></td>`, 7) + | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                 '</tr>'; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-08 19:03:00 +02:00
										 |  |  |         let days = OpeningHoursPickerTable.days.map((day, i) => { | 
					
						
							|  |  |  |             const innerContent  =  self.weekdays.data[i]?.Render() ?? ""; | 
					
						
							|  |  |  |             return day.Render() + "<span style='width:100%; display:block; position: relative;'>"+innerContent+"</span>"; | 
					
						
							|  |  |  |         }).join("</th><th width='14%'>"); | 
					
						
							| 
									
										
										
										
											2020-10-04 12:55:44 +02:00
										 |  |  |         return `<table id="oh-table-${this.id}" class="oh-table"><tr><th></th><th width='14%'>${days}</th></tr>${rows}</table>`; | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected InnerUpdate() { | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         const table = (document.getElementById(`oh-table-${this.id}`) as HTMLTableElement); | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  |         console.log("Inner update!") | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |         if (table === undefined || table === null) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (const uielement of this.weekdays.data) { | 
					
						
							|  |  |  |             uielement.Update(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let mouseIsDown = false; | 
					
						
							|  |  |  |         let selectionStart: [number, number] = undefined; | 
					
						
							|  |  |  |         let selectionEnd: [number, number] = undefined; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function h(timeSegment: number) { | 
					
						
							|  |  |  |             return Math.floor(timeSegment / 2); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function m(timeSegment: number) { | 
					
						
							|  |  |  |             return (timeSegment % 2) * 30; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function startSelection(i: number, j: number) { | 
					
						
							|  |  |  |             mouseIsDown = true; | 
					
						
							|  |  |  |             selectionStart = [i, j]; | 
					
						
							|  |  |  |             selectionEnd = [i, j]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function endSelection() { | 
					
						
							|  |  |  |             if (selectionStart === undefined) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!mouseIsDown) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             mouseIsDown = false | 
					
						
							|  |  |  |             const dStart = Math.min(selectionStart[1], selectionEnd[1]); | 
					
						
							|  |  |  |             const dEnd = Math.max(selectionStart[1], selectionEnd[1]); | 
					
						
							|  |  |  |             const timeStart = Math.min(selectionStart[0], selectionEnd[0]) - 1; | 
					
						
							|  |  |  |             const timeEnd = Math.max(selectionStart[0], selectionEnd[0]) - 1; | 
					
						
							|  |  |  |             for (let weekday = dStart; weekday <= dEnd; weekday++) { | 
					
						
							|  |  |  |                 const oh: OpeningHour = { | 
					
						
							|  |  |  |                     weekday: weekday, | 
					
						
							|  |  |  |                     startHour: h(timeStart), | 
					
						
							|  |  |  |                     startMinutes: m(timeStart), | 
					
						
							|  |  |  |                     endHour: h(timeEnd + 1), | 
					
						
							|  |  |  |                     endMinutes: m(timeEnd + 1) | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  |                 if (oh.endHour > 23) { | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                     oh.endHour = 24; | 
					
						
							|  |  |  |                     oh.endMinutes = 0; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-10-06 01:37:02 +02:00
										 |  |  |                 self.source.data.push(oh); | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-10-06 01:37:02 +02:00
										 |  |  |             self.source.ping(); | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Clear the highlighting
 | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  |             let header = table.rows[0]; | 
					
						
							|  |  |  |             for (let j = 1; j < header.cells.length; j++) { | 
					
						
							|  |  |  |                 header.cells[j].classList?.remove("oh-timecol-selected") | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |             for (let i = 1; i < table.rows.length; i++) { | 
					
						
							|  |  |  |                 let row = table.rows[i] | 
					
						
							|  |  |  |                 for (let j = 0; j < row.cells.length; j++) { | 
					
						
							|  |  |  |                     let cell = row.cells[j] | 
					
						
							| 
									
										
										
										
											2020-10-21 20:54:15 +02:00
										 |  |  |                     cell?.classList?.remove("oh-timecell-selected"); | 
					
						
							|  |  |  |                     row.classList?.remove("oh-timerow-selected"); | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         table.onmouseup = () => { | 
					
						
							|  |  |  |             endSelection(); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         table.onmouseleave = () => { | 
					
						
							|  |  |  |             endSelection(); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  |         let lastSelectionIend, lastSelectionJEnd; | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |         function selectAllBetween(iEnd, jEnd) { | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (lastSelectionIend === iEnd && lastSelectionJEnd === jEnd) { | 
					
						
							|  |  |  |                 return; // We already did this
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             lastSelectionIend = iEnd; | 
					
						
							|  |  |  |             lastSelectionJEnd = jEnd; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |             let iStart = selectionStart[0]; | 
					
						
							|  |  |  |             let jStart = selectionStart[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (iStart > iEnd) { | 
					
						
							|  |  |  |                 const h = iStart; | 
					
						
							|  |  |  |                 iStart = iEnd; | 
					
						
							|  |  |  |                 iEnd = h; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (jStart > jEnd) { | 
					
						
							|  |  |  |                 const h = jStart; | 
					
						
							|  |  |  |                 jStart = jEnd; | 
					
						
							|  |  |  |                 jEnd = h; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  |             let header = table.rows[0]; | 
					
						
							|  |  |  |             for (let j = 1; j < header.cells.length; j++) { | 
					
						
							|  |  |  |                 let cell = header.cells[j] | 
					
						
							|  |  |  |                 cell.classList?.remove("oh-timecol-selected-round-left"); | 
					
						
							|  |  |  |                 cell.classList?.remove("oh-timecol-selected-round-right"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (jStart + 1 <= j && j <= jEnd + 1) { | 
					
						
							|  |  |  |                     cell.classList?.add("oh-timecol-selected") | 
					
						
							|  |  |  |                     if (jStart + 1 == j) { | 
					
						
							|  |  |  |                         cell.classList?.add("oh-timecol-selected-round-left"); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (jEnd + 1 == j) { | 
					
						
							|  |  |  |                         cell.classList?.add("oh-timecol-selected-round-right"); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     cell.classList?.remove("oh-timecol-selected") | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |             for (let i = 1; i < table.rows.length; i++) { | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  |                 let row = table.rows[i]; | 
					
						
							|  |  |  |                 if (iStart <= i && i <= iEnd) { | 
					
						
							|  |  |  |                     row.classList?.add("oh-timerow-selected") | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     row.classList?.remove("oh-timerow-selected") | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                 for (let j = 0; j < row.cells.length; j++) { | 
					
						
							|  |  |  |                     let cell = row.cells[j] | 
					
						
							|  |  |  |                     if (cell === undefined) { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     let offset = 0; | 
					
						
							|  |  |  |                     if (i % 2 == 1) { | 
					
						
							|  |  |  |                         if (j == 0) { | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  |                             // This is the first column of a full hour -> This is the time indication (skip)
 | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                             continue; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         offset = -1; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2020-10-23 01:20:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                     if (iStart <= i && i <= iEnd && | 
					
						
							|  |  |  |                         jStart <= j + offset && j + offset <= jEnd) { | 
					
						
							|  |  |  |                         cell?.classList?.add("oh-timecell-selected") | 
					
						
							|  |  |  |                     } else { | 
					
						
							| 
									
										
										
										
											2020-10-21 20:54:15 +02:00
										 |  |  |                         cell?.classList?.remove("oh-timecell-selected")           | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2020-10-21 20:54:15 +02:00
										 |  |  |                      | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (let i = 1; i < table.rows.length; i++) { | 
					
						
							|  |  |  |             let row = table.rows[i] | 
					
						
							|  |  |  |             for (let j = 0; j < row.cells.length; j++) { | 
					
						
							| 
									
										
										
										
											2020-10-08 19:03:00 +02:00
										 |  |  |                 let cell = row.cells[j] | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                 let offset = 0; | 
					
						
							|  |  |  |                 if (i % 2 == 1) { | 
					
						
							|  |  |  |                     if (j == 0) { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     offset = -1; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 cell.onmousedown = (ev) => { | 
					
						
							|  |  |  |                     ev.preventDefault(); | 
					
						
							|  |  |  |                     startSelection(i, j + offset) | 
					
						
							|  |  |  |                     selectAllBetween(i, j + offset); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 cell.ontouchstart = (ev) => { | 
					
						
							|  |  |  |                     ev.preventDefault(); | 
					
						
							|  |  |  |                     startSelection(i, j + offset); | 
					
						
							|  |  |  |                     selectAllBetween(i, j + offset); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 cell.onmouseenter = () => { | 
					
						
							|  |  |  |                     if (mouseIsDown) { | 
					
						
							|  |  |  |                         selectionEnd = [i, j + offset]; | 
					
						
							|  |  |  |                         selectAllBetween(i, j + offset) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 cell.ontouchmove = (ev: TouchEvent) => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     ev.preventDefault(); | 
					
						
							|  |  |  |                     for (const k in ev.targetTouches) { | 
					
						
							|  |  |  |                         const touch = ev.targetTouches[k]; | 
					
						
							| 
									
										
										
										
											2020-10-05 20:42:54 +02:00
										 |  |  |                         if(touch.clientX === undefined || touch.clientY === undefined){ | 
					
						
							|  |  |  |                             continue; | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                         const elUnderTouch = document.elementFromPoint( | 
					
						
							| 
									
										
										
										
											2020-10-05 20:42:54 +02:00
										 |  |  |                             touch.clientX, | 
					
						
							|  |  |  |                             touch.clientY | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                         ); | 
					
						
							|  |  |  |                         // @ts-ignore
 | 
					
						
							|  |  |  |                         const f = elUnderTouch.onmouseenter; | 
					
						
							|  |  |  |                         if (f) { | 
					
						
							|  |  |  |                             f(); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 cell.ontouchend = (ev) => { | 
					
						
							|  |  |  |                     ev.preventDefault(); | 
					
						
							| 
									
										
										
										
											2020-10-05 20:42:54 +02:00
										 |  |  |                     endSelection(); | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 01:37:02 +02:00
										 |  |  |     IsValid(t: OpeningHour[]): boolean { | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 01:37:02 +02:00
										 |  |  |     GetValue(): UIEventSource<OpeningHour[]> { | 
					
						
							| 
									
										
										
										
											2020-10-04 01:04:46 +02:00
										 |  |  |         return this.source; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |