diff --git a/client/src/inject.ts b/client/src/inject.ts index e5660ac..6cd975a 100644 --- a/client/src/inject.ts +++ b/client/src/inject.ts @@ -10,32 +10,6 @@ import { config } from "./modules/config"; let inputsWithValue: I.InputsWithValue; let childHasVenueXML: boolean = false; -window.addEventListener('load', function () { - const content: string = new XMLSerializer().serializeToString(document); - Parser.getInputs(content, inputsWithValue) - - console.log(inputsWithValue["trxstate"]); - console.log(/posturl:"(.+?)"/.test(content)); - - // posturl absent if pvmapse === false - if (inputsWithValue["trxstate"] !== "20" || /posturl:"(.+?)"/.test(content) === false) - return; - - Utils.inject(config.urlCSSParentStaging, "css", "body"); - Communication.listenToMessages(messagesHandler); - Parser.getAdditionalInputs(content, inputsWithValue); - Parser.getImportantNote(inputsWithValue); - jQuery(".flash_seat_map_box").remove(); - UI.injectBookingBtn(); - UI.createDialog(childHasVenueXML); - - console.log(inputsWithValue); - - jQuery("#foobarParent").on("click", () => { - Communication.sendEventToChild("parent_init_venue"); - }); -}); - function messagesHandler(e: any) { if (typeof (e.data) !== 'string') return; @@ -73,4 +47,35 @@ function messagesHandler(e: any) { default: break; } -} \ No newline at end of file +} + +window.addEventListener('load', function () { + const content: string = new XMLSerializer().serializeToString(document); + inputsWithValue = { ...inputsWithValue, ...Parser.getInputs(content) }; + console.log(inputsWithValue); + + console.log(inputsWithValue["trxstate"]); + console.log(/posturl:"(.+?)"/.test(content)); + + // posturl absent if pvmapse === false + if (inputsWithValue["trxstate"] !== "20" || /posturl:"(.+?)"/.test(content) === false) + return; + + Utils.inject(config.urlCSSParentStaging, "css", "body"); + Communication.listenToMessages(messagesHandler); + inputsWithValue = { ...inputsWithValue, ...Parser.getAdditionalInputs(content) }; + + const importantNote = Parser.getImportantNote(); + if (importantNote) + inputsWithValue = { ...inputsWithValue, ...importantNote }; + + UI.injectBookingBtn(); + UI.createDialog(childHasVenueXML); + + console.log(inputsWithValue); + + // remove on production + jQuery("#foobarParent").on("click", () => { + Communication.sendEventToChild("parent_init_venue"); + }); +}); \ No newline at end of file diff --git a/client/src/modules/communication.ts b/client/src/modules/communication.ts index d6d1c46..01fee45 100644 --- a/client/src/modules/communication.ts +++ b/client/src/modules/communication.ts @@ -66,4 +66,15 @@ export function needSeatmapXML(inID: string) { date: Date.now() }; sendMessage(message, "parent"); +} + +export function showBookingBtnParent(): void { + console.log("child completely ready"); + const message: I.Message = { + message: null, + from: "child", + event: "child_seatmap_ready", + date: Date.now() + }; + sendMessage(message, "parent"); } \ No newline at end of file diff --git a/client/src/modules/jsc.ts b/client/src/modules/jsc.ts new file mode 100644 index 0000000..bc8f6dc --- /dev/null +++ b/client/src/modules/jsc.ts @@ -0,0 +1,118 @@ +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", + "seatsObj": pricescaleArr[key] + } + const seatsKey: string = String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase(); + object[seatsKey] = seatsObj; + } + + const seatmapInitSeats: I.JSCSeats = object; + + return seatmapInitSeats; +} + +export function getRows(inXML: any): number[] { + const layout: I.SeatmapLayout = inXML.seatmap[0].layouts[0].layout[0]; + const height: number = parseInt(layout.height[0]); + + return Array.from({ length: height }, (_, i: number) => i + 1); +} + +export function generateMap(inXML: any): string[] { + const layout: I.SeatmapLayout = inXML.seatmap[0].layouts[0].layout[0]; + console.log(layout); + const rows: I.LayoutRow2[] = layout.rows[0].row; + const pricescaleArr: I.SeatmapPricescale[] = inXML.seatmap[0].pricescale_config[0].pricescale; + + // Form: arrMatrix[Y][X] + let arrMatrix: string[][] = createArrMatrix(parseInt(layout.height[0]), parseInt(layout.width[0]), "_"); + + arrMatrix = enterSeatsInMatrix(rows, arrMatrix, pricescaleArr); + const stringArrMatrix = generateStringArrMatrix(arrMatrix); + + return stringArrMatrix; +} + +export function generateStringArrMatrix(inArrMatrix: string[][]): string[] { + const stringArrMatrix: string[] = []; + + inArrMatrix.forEach(element => { + stringArrMatrix.push(element.join("")); + }); + + return stringArrMatrix; +} + + +export function enterSeatsInMatrix(inRows: I.LayoutRow2[], inArrMatrix: string[][], inPricescaleArr: I.SeatmapPricescale[]): string[][] { + inRows.forEach(element => { + const row: I.LayoutRow2 = element; + const Y: number = parseInt(row.y_cell_coord[0]); + const seatsArr: string[] = row.seats[0].split("|"); + + seatsArr.forEach(element => { + const seatStr: string = element; + // Form: + // "568420,568420,15,7024,13 ,1" + + const seatArr: string[] = splitSeatStr(seatStr); + // Form: + // 0: "568528" + // 1: "568528" + // 2: "21" + // 3: "7024" + // 4: "13" + // 5: "4" + + const X: number = parseInt(seatArr[5]); + const seatsKey = getSeatsKey(seatArr[0], inPricescaleArr); + + if (seatsKey) + inArrMatrix[Y][X] = generateSeatStr(seatsKey, seatArr); + }); + }); + + return inArrMatrix; +} + +export function getSeatsKey(inSeatID: string, inPricescaleArr: I.SeatmapPricescale[]): string | undefined { + for (let key in inPricescaleArr) { + if (inPricescaleArr[key].mask[0].includes(inSeatID)) + return String.fromCharCode(97 + parseInt(key)).toLocaleUpperCase(); + } + + return undefined; +} + +export function generateSeatStr(seatLetter: string, seatArr: string[]): string { + return `${seatLetter}[${seatArr[0]}, ]`; +} + +export function splitSeatStr(inSeatStr: string): string[] { + const seatArr: string[] = inSeatStr.split(",").map(function (item) { + return item.trim(); + }); + + return seatArr; +} + +export function createArrMatrix(inNumrows: number, inNumcols: number, inInitial: string) { + var arr: string[][] = []; + for (let i: number = 0; i < inNumrows; ++i) { + let columns: string[] = []; + for (let j: number = 0; j < inNumcols; ++j) { + columns[j] = inInitial; + } + arr[i] = columns; + } + + return arr; +} \ No newline at end of file diff --git a/client/src/modules/parser.ts b/client/src/modules/parser.ts index 1e74766..1e4c80a 100644 --- a/client/src/modules/parser.ts +++ b/client/src/modules/parser.ts @@ -9,8 +9,8 @@ export function getVenueLocation(): string { return span.join(", "); } -export function getInputs(inContent: string, inInputsWithValue: I.InputsWithValue): void { - const parsedHTML: Node[] = $.parseHTML(inContent); +export function getInputs(inContent: string): I.Inputs { + const parsedHTML: Node[] = jQuery.parseHTML(inContent); let inputs: I.Inputs = {}; jQuery(parsedHTML).find('input').each(function (this: any) { @@ -20,25 +20,38 @@ export function getInputs(inContent: string, inInputsWithValue: I.InputsWithValu inputs[name] = value; }); - inInputsWithValue = { ...inInputsWithValue, ...inputs }; + return inputs; } // todo: check with different venues -export function getImportantNote(inInputsWithValue: I.InputsWithValue): void { - const importantNote: string | null = $(".important_note")[0].textContent; +export function getImportantNote(): { importantNote: string, importantNoteEncoded: string } | undefined { + const importantNote: string | null = jQuery(".important_note")[0].textContent; if (importantNote?.trim().length) { const importantNoteEncoded: string = encodeURIComponent(importantNote); - inInputsWithValue["importantNote"] = importantNote; - inInputsWithValue["importantNoteEncoded"] = importantNoteEncoded; + return { + "importantNote": importantNote, + "importantNoteEncoded": importantNoteEncoded + } } + + return undefined; } -export function getAdditionalInputs(inContent: string, inInputsWithValue: I.InputsWithValue): void { - inInputsWithValue["event"] = inContent.match(/event:"(.+?)"/)![1]; - inInputsWithValue["holdcode"] = inContent.match(/holdcode:"(.+?)"/)![1]; - inInputsWithValue["posturlRaw"] = inContent.match(/posturl:"(.+?)"/)![1]; - inInputsWithValue["posturlRawDecoded"] = decodeURIComponent(inInputsWithValue["posturlRaw"]); - inInputsWithValue["posturl"] = decodeURIComponent(`${inInputsWithValue["posturlRaw"]}&event=${inInputsWithValue["event"]}&holdcode=${inInputsWithValue["holdcode"]}&nocache=0&inclpkg=Y&incloffer=Y&inclcartdetails=Y&inclCart=Y&inclvenue=Y`); - inInputsWithValue["venueLocation"] = getVenueLocation(); +export function getAdditionalInputs(inContent: string): { [key: string]: string } { + const event = inContent.match(/event:"(.+?)"/)![1]; + const holdcode = inContent.match(/holdcode:"(.+?)"/)![1]; + const posturlRaw = inContent.match(/posturl:"(.+?)"/)![1]; + const posturlRawDecoded = decodeURIComponent(posturlRaw); + const posturl = decodeURIComponent(`${posturlRaw}&event=${event}&holdcode=${holdcode}&nocache=0&inclpkg=Y&incloffer=Y&inclcartdetails=Y&inclCart=Y&inclvenue=Y`); + const venueLocation = getVenueLocation() + + return { + "event": event, + "holdcode": holdcode, + "posturlRaw": posturlRaw, + "posturlRawDecoded": posturlRawDecoded, + "posturl": posturl, + "venueLocation": venueLocation + } } \ No newline at end of file diff --git a/client/src/modules/ui.ts b/client/src/modules/ui.ts index 1334f6a..f1ef54c 100644 --- a/client/src/modules/ui.ts +++ b/client/src/modules/ui.ts @@ -1,5 +1,6 @@ import * as I from "../types/types"; import * as Communication from "./communication"; +import Panzoom from '@panzoom/panzoom'; export function setOptionSelect(inSeatmapListing: I.Seatmap[], inId: string) { const seatmapDropdown: HTMLElement | null = document.getElementById(inId); @@ -50,6 +51,7 @@ export function createDialog(inChildHasVenueXML: boolean): void { } export function injectBookingBtn(): void { + jQuery(".flash_seat_map_box").remove(); jQuery('#flash_seat_map_box_id').css({ "display": "block", "position": "relative", @@ -68,4 +70,49 @@ export function injectBookingBtn(): void {
`); +} + +export function destroyCurrentSeatmap(): void { + jQuery("#containerSeatmapInner").remove(); + jQuery("#htmlSeatmapInner .fl-html").removeAttr("style"); + jQuery("#htmlSeatmapInner .fl-html").append(''); +} + +export function controlLoftloader(inSwitch: string) { + if (inSwitch === "show") + jQuery("body").removeClass("loaded loftloader-loaded"); + else if (inSwitch === "hide") + jQuery("body").addClass("loaded loftloader-loaded"); +} + +export function addPanzoom(inSelector: string, inBtnZoomIn: string | null = null, inBtnZoomOut: string | null = null, inBtnResetZoom: string | null = null) { + const container: HTMLElement = jQuery(inSelector).get(0); + if (container) { + const panzoom = Panzoom(container, { + maxScale: 5, + animate: false, + overflow: "hidden", + }); + + container.parentElement!.addEventListener('wheel', panzoom.zoomWithWheel); + + if (inBtnZoomIn) { + const btnZoomIn: HTMLElement | undefined = jQuery(inBtnZoomIn).get(0); + if (btnZoomIn) + btnZoomIn.addEventListener('click', panzoom.zoomIn); + } + + if (inBtnZoomOut) { + const btnZoomOut: HTMLElement | undefined = jQuery(inBtnZoomOut).get(0); + if (btnZoomOut) + btnZoomOut.addEventListener('click', panzoom.zoomOut); + } + + if (inBtnResetZoom) { + const btnResetZoom: HTMLElement | undefined = jQuery(inBtnResetZoom).get(0); + if (btnResetZoom) + btnResetZoom.addEventListener('click', panzoom.reset); + } + + } } \ No newline at end of file diff --git a/client/src/seatmap.ts b/client/src/seatmap.ts index d448250..80daf44 100644 --- a/client/src/seatmap.ts +++ b/client/src/seatmap.ts @@ -3,74 +3,109 @@ import * as XMLHelper from "./modules/xml"; 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 Panzoom from '@panzoom/panzoom'; -// var sc = require("../libs/jQuery-Seat-Charts/jquery.seat-charts.js"); -// var parseString = require('xml2js').parseString; -// import axios from 'axios'; -// import Utils from './utils'; -// let checkoutParams: string[]; -// let posturl: string; - let inputsWithValue: I.InputsWithValue; let seatmap: any; +function messagesHandler(inE: any) { + if (typeof (inE.data) !== 'string') + return; + + const data: I.Message = JSON.parse(inE.data); + console.log(`child: received from ${data.from}`); + 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; + + // fill event info + const eventInfo = XMLHelper.getEventInfo(XML); + UI.setEventInfo(eventInfo, inputsWithValue); + + // fill select dropdown + const seatmapListing: I.Seatmap[] = XMLHelper.getSeatmapListing(XML); + console.log(seatmapListing); + UI.setOptionSelect(seatmapListing, "dropdownSeatmap"); + + // display first seatmapXML + const id: string = seatmapListing[0].id[0]; + jQuery("#dropdownSeatmap").val(id); + Communication.needSeatmapXML(id); + + break; + } + case "parent_init_sendInputsWithValue": { + inputsWithValue = data.message; + 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); + + addSeatmap("#containerSeatmapInner", seatmapInitMap, seatmapInitRows, seatmapInitSeats); + UI.addPanzoom("#containerSeatmapInner", ".panzoomZoomIn", ".panzoomZoomOut", "#panzoomResetZoom"); + + UI.controlLoftloader("hide"); + break; + } + + + default: + break; + } +} + window.addEventListener('load', function () { - - jQuery("#foobar").on("click", () => { - Communication.sendMessage(