diff --git a/client/src/inject.ts b/client/src/inject.ts
index 6cd975a..06c25d7 100644
--- a/client/src/inject.ts
+++ b/client/src/inject.ts
@@ -64,6 +64,7 @@ window.addEventListener('load', function () {
Utils.inject(config.urlCSSParentStaging, "css", "body");
Communication.listenToMessages(messagesHandler);
inputsWithValue = { ...inputsWithValue, ...Parser.getAdditionalInputs(content) };
+ inputsWithValue = { ...inputsWithValue, ...Parser.getVenueImage() };
const importantNote = Parser.getImportantNote();
if (importantNote)
diff --git a/client/src/modules/communication.ts b/client/src/modules/communication.ts
index 01fee45..9e73efc 100644
--- a/client/src/modules/communication.ts
+++ b/client/src/modules/communication.ts
@@ -1,5 +1,5 @@
import * as I from "../types/types";
-import * as xml from "./xml";
+import * as xml from "./xmlhelper";
// rework try/catch ?
export function sendMessage(data: I.Message, to: string): void {
diff --git a/client/src/modules/jsc.ts b/client/src/modules/jsc.ts
index bc8f6dc..74789e5 100644
--- a/client/src/modules/jsc.ts
+++ b/client/src/modules/jsc.ts
@@ -1,13 +1,12 @@
import * as I from "../types/types";
-
export function getSeats(inXML: any): I.JSCSeats {
const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
let object: any = {};
for (let key in pricescaleArr) {
const seatsObj: I.JSCSeats2 = {
- "classes": "foobar",
+ "classes": `_${pricescaleArr[key].id[0]}`,
"seatsObj": pricescaleArr[key]
}
const seatsKey: string = String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase();
@@ -19,6 +18,17 @@ export function getSeats(inXML: any): I.JSCSeats {
return seatmapInitSeats;
}
+export function activateSeatsBySectionID(inXML: any, seatmap: any, inValue: string, ) {
+ const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
+
+ pricescaleArr.forEach(element => {
+ if (element.id[0] === inValue) {
+ const seatsArr = element.mask[0].split(",");
+ seatmap.status(seatsArr, "available");
+ }
+ });
+}
+
export function getRows(inXML: any): number[] {
const layout: I.SeatmapLayout = inXML.seatmap[0].layouts[0].layout[0];
const height: number = parseInt(layout.height[0]);
@@ -41,6 +51,34 @@ export function generateMap(inXML: any): string[] {
return stringArrMatrix;
}
+export function generateLegend(inXML: any, inNode: string): I.JSCLegend {
+ const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale;
+ console.log(pricescaleArr);
+ let legend: I.JSCLegend = {
+ node: jQuery(inNode),
+ items: []
+ }
+
+ for (let key in pricescaleArr) {
+ const seatsKey: string = String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase();
+ const price: string = `€${pricescaleArr[key].ref_price[0]}`;
+ const legendItem = [ seatsKey, "available", price ];
+ legend.items.push(legendItem);
+ }
+
+ return legend;
+}
+
+export function setUnavailableSeats(inXML: any, seatmap: any): void {
+ const availabilityArr: I.JSCAvailability = inXML.seatmap[0].view_modes[0].view_mode[0].availability[0];
+
+ if (availabilityArr.unavailable_unselectable_mask[0] === "")
+ return;
+
+ const unavailableArr: string[] = availabilityArr.unavailable_unselectable_mask[0].split(",");
+ seatmap.status(unavailableArr, "unavailable");
+}
+
export function generateStringArrMatrix(inArrMatrix: string[][]): string[] {
const stringArrMatrix: string[] = [];
@@ -65,14 +103,15 @@ export function enterSeatsInMatrix(inRows: I.LayoutRow2[], inArrMatrix: string[]
const seatArr: string[] = splitSeatStr(seatStr);
// Form:
- // 0: "568528"
- // 1: "568528"
- // 2: "21"
- // 3: "7024"
- // 4: "13"
- // 5: "4"
+ // 0: "568528" -> ID
+ // 1: "568528" -> ID
+ // 2: "21" -> X-Coord benutzen
+ // 3: "7024" -> section ID
+ // 4: "13" -> Reihenbezeichnung
+ // 5: "4" -> ?
- const X: number = parseInt(seatArr[5]);
+ // const X: number = parseInt(seatArr[5]);
+ const X: number = parseInt(seatArr[2]);
const seatsKey = getSeatsKey(seatArr[0], inPricescaleArr);
if (seatsKey)
diff --git a/client/src/modules/parser.ts b/client/src/modules/parser.ts
index 1e4c80a..bd643b1 100644
--- a/client/src/modules/parser.ts
+++ b/client/src/modules/parser.ts
@@ -1,8 +1,9 @@
import * as I from "../types/types";
+var jQuery = require("jquery");
export function getVenueLocation(): string {
let span: string[] = [];
- jQuery(".venue span").each(function () {
+ jQuery(".venue span").each(function (this: any) {
span.push(jQuery(this).text());
});
@@ -25,15 +26,17 @@ export function getInputs(inContent: string): I.Inputs {
// todo: check with different venues
export function getImportantNote(): { importantNote: string, importantNoteEncoded: string } | undefined {
- const importantNote: string | null = jQuery(".important_note")[0].textContent;
+ if (jQuery(".important_note").length) {
+ const importantNote: string | null = jQuery(".important_note")[0].textContent;
- if (importantNote?.trim().length) {
- const importantNoteEncoded: string = encodeURIComponent(importantNote);
- return {
- "importantNote": importantNote,
- "importantNoteEncoded": importantNoteEncoded
- }
- }
+ if (importantNote?.trim().length) {
+ const importantNoteEncoded: string = encodeURIComponent(importantNote);
+ return {
+ "importantNote": importantNote,
+ "importantNoteEncoded": importantNoteEncoded
+ }
+ }
+ }
return undefined;
}
@@ -54,4 +57,18 @@ export function getAdditionalInputs(inContent: string): { [key: string]: string
"posturl": posturl,
"venueLocation": venueLocation
}
+}
+
+export function getVenueImage(): { venueImageSrc: string, venueImageHeight: number, venueImageWidth: number } | undefined {
+ const img: HTMLImageElement = jQuery("#static_venue_map img").get(0);
+
+ if (img) {
+ return {
+ venueImageSrc: img.src,
+ venueImageHeight: img.height,
+ venueImageWidth: img.width
+ }
+ }
+
+ return undefined;
}
\ No newline at end of file
diff --git a/client/src/modules/ui.ts b/client/src/modules/ui.ts
index f1ef54c..56bf968 100644
--- a/client/src/modules/ui.ts
+++ b/client/src/modules/ui.ts
@@ -1,6 +1,7 @@
import * as I from "../types/types";
import * as Communication from "./communication";
import Panzoom from '@panzoom/panzoom';
+import { PanzoomObject } from "@panzoom/panzoom/dist/src/types";
export function setOptionSelect(inSeatmapListing: I.Seatmap[], inId: string) {
const seatmapDropdown: HTMLElement | null = document.getElementById(inId);
@@ -72,10 +73,35 @@ export function injectBookingBtn(): void {
`);
}
-export function destroyCurrentSeatmap(): void {
+export function convertLegendToDropdown(inID: string) {
+ jQuery('ul.seatCharts-legendList').each(function() {
+ let select = jQuery(document.createElement('select')).insertBefore(jQuery(this).hide());
+ select.attr({ id: inID});
+ let option = jQuery('');
+ option.attr({ 'value': 'all' }).text('Alle Preiskategorien');
+ option.css("color", "#5c5c5c");
+ select.append(option);
+ jQuery('>li', this).each(function() {
+ const className = jQuery(this)[0].children[0].classList[3];
+ const val = className.substring(1);
+ const text = (jQuery(this)[0].children[1]).innerText;
+ let option = jQuery('');
+
+ option.attr({ 'value': val, 'class': className }).text(text);
+ select.append(option);
+ });
+ });
+}
+
+export function destroyCurrentSeatmap(inSelector: string, inPanzoom: PanzoomObject | undefined): void {
+ if (inPanzoom)
+ unbindPanzoomEvents(inSelector, inPanzoom);
+
jQuery("#containerSeatmapInner").remove();
jQuery("#htmlSeatmapInner .fl-html").removeAttr("style");
jQuery("#htmlSeatmapInner .fl-html").append('');
+ jQuery("#JSCLegendInner").remove();
+ jQuery("#JSCLegend .fl-html").append('');
}
export function controlLoftloader(inSwitch: string) {
@@ -85,10 +111,16 @@ export function controlLoftloader(inSwitch: string) {
jQuery("body").addClass("loaded loftloader-loaded");
}
-export function addPanzoom(inSelector: string, inBtnZoomIn: string | null = null, inBtnZoomOut: string | null = null, inBtnResetZoom: string | null = null) {
+function unbindPanzoomEvents(inSelector: string, inPanzoom: PanzoomObject): void {
+ console.log("unbinding now");
+ const container: HTMLElement = jQuery(inSelector).get(0);
+ container.parentElement?.removeEventListener('wheel', inPanzoom.zoomWithWheel);
+}
+
+export function addPanzoom(inSelector: string, inBtnZoomIn: string | null = null, inBtnZoomOut: string | null = null, inBtnResetZoom: string | null = null): PanzoomObject | undefined {
const container: HTMLElement = jQuery(inSelector).get(0);
if (container) {
- const panzoom = Panzoom(container, {
+ const panzoom: PanzoomObject = Panzoom(container, {
maxScale: 5,
animate: false,
overflow: "hidden",
@@ -114,5 +146,13 @@ export function addPanzoom(inSelector: string, inBtnZoomIn: string | null = null
btnResetZoom.addEventListener('click', panzoom.reset);
}
+ return panzoom;
}
+
+ return undefined;
+}
+
+export function changeVenueImage(inInputsWithValue: I.InputsWithValue) {
+ if (inInputsWithValue.venueImageSrc !== undefined)
+ jQuery("#venueImage img").attr("src", inInputsWithValue.venueImageSrc);
}
\ No newline at end of file
diff --git a/client/src/modules/utils.ts b/client/src/modules/utils.ts
index 3eed204..7e15f7f 100644
--- a/client/src/modules/utils.ts
+++ b/client/src/modules/utils.ts
@@ -1,7 +1,7 @@
export default class Utils {
static waitForElement(selector: any, callback: Function, type: string = "selector", checkFrequencyInMs: number = 1000, timeoutInMs: number = 10000) {
- let startTimeInMs: number = Date.now();
+ let startTimeInMs: number = Date.now();
(function loopSearch(): void {
let value: boolean;
console.log(selector);
@@ -16,7 +16,7 @@ export default class Utils {
if (value) {
console.log("defined");
callback();
- }
+ }
else {
setTimeout(function (): void {
console.log("repeating");
@@ -24,18 +24,18 @@ export default class Utils {
return;
loopSearch();
}, checkFrequencyInMs);
- }
+ }
})();
}
static waitForSeatmap(callback: Function, checkFrequencyInMs: number = 100, timeoutInMs: number = 10000) {
const seatCharts: any = (window).jQuery("#containerSeatmap").seatCharts;
- let startTimeInMs: number = Date.now();
+ let startTimeInMs: number = Date.now();
if (Utils.isFunction(seatCharts)) {
console.log("defined");
callback();
- }
+ }
else {
setTimeout(function (): void {
console.log("repeating");
@@ -50,7 +50,7 @@ export default class Utils {
if (document.querySelector(selector) != null)
return true;
else
- return false;
+ return false;
}
static isFunction(selector: string): boolean {
@@ -64,21 +64,26 @@ export default class Utils {
return new Promise(resolve => setTimeout(resolve, ms));
}
- static inject(content: string, type: string = "js", loc: string = "head") {
- var script: HTMLLinkElement | HTMLScriptElement;
+ static inject(content: string, inType: string = "js", inLoc: string = "head") {
+ var script: HTMLLinkElement | HTMLScriptElement | HTMLStyleElement;
- if (type === "js") {
+ if (inType === "js") {
script = document.createElement('script');
script.type = 'text/javascript';
script.src = content;
}
- else if (type === "css") {
+ else if (inType === "css") {
script = document.createElement('link');
script.type = 'text/css';
- script.rel = "stylesheet"
- script.href = content;
+ (script).rel = "stylesheet";
+ (script).href = content;
}
- else if (type === "script") {
+ else if (inType === "cssCustom") {
+ script = document.createElement('style');
+ script.type = 'text/css';
+ script.innerHTML = content;
+ }
+ else if (inType === "script") {
script = document.createElement('script');
script.type = 'text/javascript';
script.innerHTML = content;
@@ -86,15 +91,20 @@ export default class Utils {
else
return;
-
- if (loc === "body")
+ if (inLoc === "body")
document.body.appendChild(script);
- else if (loc === "head")
+ else if (inLoc === "head")
document.head.appendChild(script);
}
static getDayName(date: Date, locale: string) {
- return date.toLocaleDateString(locale, { weekday: 'long' });
+ return date.toLocaleDateString(locale, { weekday: 'long' });
+ }
+
+ static generateRandomColor(): string {
+ const randomNumber: number = Math.floor((Math.random() * 10000) + 1);
+ const hue = randomNumber * 137.508; // use golden angle approximation
+ return `hsl(${hue},100%,75%)`;
}
}
diff --git a/client/src/modules/xml.ts b/client/src/modules/xmlhelper.ts
similarity index 100%
rename from client/src/modules/xml.ts
rename to client/src/modules/xmlhelper.ts
diff --git a/client/src/seatmap.ts b/client/src/seatmap.ts
index 80daf44..a1f85fc 100644
--- a/client/src/seatmap.ts
+++ b/client/src/seatmap.ts
@@ -1,14 +1,18 @@
import jQuery = require("jquery");
-import * as XMLHelper from "./modules/xml";
+import * as XMLHelper from "./modules/xmlhelper";
import * as Communication from "./modules/communication";
import * as I from "./types/types";
import * as UI from "./modules/ui";
import * as JSC from "./modules/jsc";
import { config } from "./modules/config";
import Utils from './modules/utils';
+import { PanzoomObject } from "@panzoom/panzoom";
let inputsWithValue: I.InputsWithValue;
let seatmap: any;
+let panzoom: PanzoomObject | undefined;
+let venueXML: I.VenueXML;
+let seatmapXML: any;
function messagesHandler(inE: any) {
if (typeof (inE.data) !== 'string')
@@ -19,75 +23,81 @@ function messagesHandler(inE: any) {
console.log(data);
switch (data.event) {
- case "RefreshDropdown": {
- const venueXML: I.VenueXML = data.message.map_response;
- const seatmapListing: I.Seatmap[] = XMLHelper.getSeatmapListing(venueXML);
- UI.setOptionSelect(seatmapListing, "dropdownSeatmap");
- break;
- }
- case "addDropdown": {
- console.log("adding to dropdown now...");
- var min = 12,
- max = 100,
- select = document.getElementById('dropdownSeatmap');
-
- for (var i = min; i <= max; i++) {
- var opt = document.createElement('option');
- opt.value = i.toString();
- opt.innerHTML = i.toString();
- select!.appendChild(opt);
- }
- break;
- }
case "parent_init_venue": {
UI.controlLoftloader("show");
Communication.sendEventToParent("child_init_needInputsWithValue");
break;
}
case "parent_init_sendVenueXML": {
- const XML: I.VenueXML = data.message.map_response;
+ venueXML = data.message.map_response;
+
+ // generate pricescale css classes
+ const css = generatePricescaleCSS(venueXML);
+ Utils.inject(css, "cssCustom", "body");
+ console.log(css);
// fill event info
- const eventInfo = XMLHelper.getEventInfo(XML);
+ const eventInfo = XMLHelper.getEventInfo(venueXML);
UI.setEventInfo(eventInfo, inputsWithValue);
// fill select dropdown
- const seatmapListing: I.Seatmap[] = XMLHelper.getSeatmapListing(XML);
+ const seatmapListing: I.Seatmap[] = XMLHelper.getSeatmapListing(venueXML);
console.log(seatmapListing);
UI.setOptionSelect(seatmapListing, "dropdownSeatmap");
// display first seatmapXML
const id: string = seatmapListing[0].id[0];
jQuery("#dropdownSeatmap").val(id);
- Communication.needSeatmapXML(id);
+ Communication.needSeatmapXML(id);
break;
}
case "parent_init_sendInputsWithValue": {
inputsWithValue = data.message;
+ UI.changeVenueImage(inputsWithValue);
Communication.sendEventToParent("child_init_needVenueXML");
break;
}
case "parent_sendSeatmapXML": {
- const XML: any = data.message.map_response;
- const seatmapInitMap: string[] = JSC.generateMap(XML);
- const seatmapInitRows: number[] = JSC.getRows(XML);
- const seatmapInitSeats: I.JSCSeats = JSC.getSeats(XML);
- console.log(seatmapInitSeats);
+ seatmapXML = data.message.map_response;
+ const map: string[] = JSC.generateMap(seatmapXML);
+ const rows: number[] = JSC.getRows(seatmapXML);
+ const seats: I.JSCSeats = JSC.getSeats(seatmapXML);
+ const legend: I.JSCLegend = JSC.generateLegend(seatmapXML, "#JSCLegendInner");
- addSeatmap("#containerSeatmapInner", seatmapInitMap, seatmapInitRows, seatmapInitSeats);
- UI.addPanzoom("#containerSeatmapInner", ".panzoomZoomIn", ".panzoomZoomOut", "#panzoomResetZoom");
+ addSeatmap("#containerSeatmapInner", map, rows, seats, legend);
+ JSC.setUnavailableSeats(seatmapXML, seatmap);
+ UI.convertLegendToDropdown("dropdownLegend");
+ dropdownLegendOnChange("#dropdownLegend");
+ panzoom = UI.addPanzoom("#containerSeatmapInner", ".panzoomZoomIn", ".panzoomZoomOut", "#panzoomResetZoom");
UI.controlLoftloader("hide");
break;
}
-
default:
break;
}
}
+function generatePricescaleCSS(inVenueXML: I.VenueXML): string {
+ const venuePricescalesArr: I.Pricescale2[] = inVenueXML.venue[0].pricescales[0].pricescale;
+ let cssArr: string[] = [];
+
+ venuePricescalesArr.forEach(element => {
+ const ID: string = element.id[0];
+
+ // todo: check if "" is correct when no color is set
+ let color: string = `#${element.color[0]} !important`;
+ if (color === "")
+ color = Utils.generateRandomColor();
+
+ cssArr.push(`._${ID} { background-color: ${color}; }`);
+ });
+
+ return (cssArr.join("\r\n"));
+}
+
window.addEventListener('load', function () {
Utils.inject(config.urlJSCStaging, "js", "head");
Utils.inject(config.urlCSSJSCStaging, "css", "body");
@@ -100,13 +110,55 @@ window.addEventListener('load', function () {
dropdownSeatmap.addEventListener("change", function (this: HTMLSelectElement) {
UI.controlLoftloader("show");
const value: string = this.value;
- UI.destroyCurrentSeatmap();
+ UI.destroyCurrentSeatmap("#containerSeatmapInner", panzoom);
Communication.needSeatmapXML(value);
});
}
+
+ // Utils.waitForElement("#dropdownLegend", dropdownLegendOnChange);
});
-function addSeatmap(inSelector: string, inSeatmapInitMap: string[], inSeatmapInitRows: number[], inSeats: I.JSCSeats): void {
+function dropdownLegendOnChange(inSelector: string) {
+ const dropdownLegend = jQuery(inSelector).get(0);
+ dropdownLegend.addEventListener("change", function (this: HTMLSelectElement) {
+ const value: string = this.value;
+ const className: string = `._${value}`;
+
+ changeDropdownLegendBGColor(inSelector, value, className);
+
+ if (value === "all") {
+ seatmap.find('unavailable').status('available');
+ JSC.setUnavailableSeats(seatmapXML, seatmap);
+ }
+ else {
+ seatmap.find('available').status('unavailable');
+ JSC.activateSeatsBySectionID(seatmapXML, seatmap, value);
+ JSC.setUnavailableSeats(seatmapXML, seatmap);
+ }
+
+ });
+}
+
+
+function changeDropdownLegendBGColor(inSelector: string, inValue: string, inClassName: string) {
+ let bgColor: string = "#fafafa";
+ let color: string = "#5c5c5c";
+
+ if (inValue !== "all") {
+ color = "white";
+ bgColor = jQuery(inClassName).css("background-color");
+ }
+
+ jQuery(inSelector).css("color", color);
+ jQuery(inSelector).css("background-color", bgColor);
+ jQuery(`${inSelector} option[value="all"]`).css("color", color);
+}
+
+function addSeatmap(inSelector: string, inMap: string[], inRows: number[], inSeats: I.JSCSeats, inLegend: I.JSCLegend): void {
+
+ // console.log(inSeatmapInitMap);
+ // console.log(inSeats);
+ // console.log(inLegend);
const containerSeatmap: any = (window).jQuery(inSelector);
@@ -114,9 +166,9 @@ function addSeatmap(inSelector: string, inSeatmapInitMap: string[], inSeatmapIni
naming: {
top: false,
left: true,
- rows: inSeatmapInitRows,
+ rows: inRows,
},
- map: inSeatmapInitMap,
+ map: inMap,
// map: [
// 'aaaaaa__DDDDD',
// 'aaaaaa__aaaaa',
@@ -134,6 +186,7 @@ function addSeatmap(inSelector: string, inSeatmapInitMap: string[], inSeatmapIni
// }
// },
+ legend: inLegend,
click: function () {
if (this.status() == 'available') {
console.log("available");
diff --git a/client/src/types/types.d.ts b/client/src/types/types.d.ts
index 02ada18..782d844 100644
--- a/client/src/types/types.d.ts
+++ b/client/src/types/types.d.ts
@@ -39,7 +39,9 @@ export interface InputsWithValue {
seatmapUrl: string;
importantNote?: string;
importantNoteEncoded?: string;
-
+ venueImageSrc: string;
+ venueImageHeight: number;
+ venueImageWidth: number;
}
export interface Config {
@@ -322,4 +324,16 @@ export interface JSCSeats2 {
export interface JSCSeats {
[key: string]: JSCSeats2;
+}
+
+// legend object
+export interface JSCLegend {
+ node: JQuery;
+ items: string[][];
+}
+
+// availability object
+export interface JSCAvailability {
+ available_selectable_mask: string[];
+ unavailable_unselectable_mask: string[];
}
\ No newline at end of file
diff --git a/client/tsconfig.json b/client/tsconfig.json
index 271e638..5a37c29 100644
--- a/client/tsconfig.json
+++ b/client/tsconfig.json
@@ -72,7 +72,7 @@
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": [
- "src/**/*.ts",
+ "src/**/*.ts"
],
"exclude": [
"node_modules"