UNPKG

d3-seating-chart-inti

Version:

A simple but pleasant seating chart written using d3js, was based on d3-seating-chart

593 lines (566 loc) 20.3 kB
webpackJsonp([0,1],{ /***/ 177: /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const D3SeatingChart_1 = __webpack_require__(51); const showBehavior_enum_1 = __webpack_require__(50); let d3sc = D3SeatingChart_1.D3SeatingChart.attach(document.getElementById('x'), { showBehavior: showBehavior_enum_1.ShowBehavior.AllDecendants, allowManualSelection: true }); var unreg = d3sc.registerZoomChangeListener(() => { console.log('zoom evt should run once'); unreg(); }); d3sc.registerZoomChangeListener(() => { console.log('zoom evt should run everytime'); console.log('History'); console.log(d3sc.history); console.log('------'); }); var unreg2 = d3sc.registerSelectionChangeListener((e) => { console.log('select evt should run once'); console.log(e); unreg2(); }); d3sc.registerSelectionChangeListener((e) => { console.log(e); console.log('select evt should run everytime'); }); document.getElementById('goToBoard').onclick = function () { d3sc.goToBoard(); }; document.getElementById('refresh').onclick = function () { d3sc.refresh(); }; document.getElementById('goBack').onclick = function () { if (d3sc.canGoBack()) { d3sc.goBack(); } else { console.log('you cant go back'); } }; document.getElementById('lock').onclick = function () { d3sc.lock('[seat="5"]'); }; document.getElementById('unlock').onclick = function () { d3sc.unlock('[seat="5"]'); }; document.getElementById('select').onclick = function () { d3sc.select('[seat="5"]'); }; document.getElementById('deselect').onclick = function () { d3sc.deselect('[seat="5"]'); }; document.getElementById('reserve').onclick = function () { d3sc.lock('[seat="5"]', 'reserved'); }; document.getElementById('unreserve').onclick = function () { d3sc.unlock('[seat="5"]'); }; document.getElementById('closest1').onclick = function () { d3sc.select(d3sc.getClosestSeats('left', 3, false)); }; /***/ }), /***/ 50: /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var ShowBehavior; (function (ShowBehavior) { ShowBehavior[ShowBehavior["All"] = 1] = "All"; ShowBehavior[ShowBehavior["DirectDecendants"] = 2] = "DirectDecendants"; ShowBehavior[ShowBehavior["AllDecendants"] = 3] = "AllDecendants"; })(ShowBehavior = exports.ShowBehavior || (exports.ShowBehavior = {})); /***/ }), /***/ 51: /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const d3 = __webpack_require__(52); const style_inline_1 = __webpack_require__(93); const showBehavior_enum_1 = __webpack_require__(50); const selectionChangeEvent_model_1 = __webpack_require__(94); const D3SeatingChartDefaultConfig = { showBehavior: showBehavior_enum_1.ShowBehavior.DirectDecendants, allowManualSelection: true }; class D3SeatingChart { constructor(element) { this.element = element; this.margin = 20; this.history = []; this.zoomChangedListeners = []; this.selectionChangeListeners = []; this.selectedElements = []; } init(config) { let svgSelection = d3.select(this.element); let gSelection = svgSelection.select("g"); this.config = config; this.uniqueIdentifier = `d3sc_${Math.round(Math.random() * 10000000000)}`; this.element.setAttribute(this.uniqueIdentifier, ""); let style = document.createElement("style"); style.innerHTML = style_inline_1.InlineStyle.replace(/\{@uid\}/g, this.uniqueIdentifier); this.element.appendChild(style); this.bindEvents(); this.zoom(gSelection, false); } stripStyles(selector) { let svgSelection = d3.select(this.element); svgSelection .selectAll(selector) .attr("stroke", null) .attr("stroke-width", null) .attr("fill", null); } getBoard() { return this.selectElement("[board]"); } selectElement(query) { return d3.select(this.element).select(query); } selectElements(query) { return d3.select(this.element).selectAll(query); } goToBoard() { this.zoom(this.getBoard()); } clearHistory() { this.history.length = 0; } canGoBack() { return !!this.history.length; } goBack() { this.history.pop(); if (this.history.length) { this.zoom(this.history[this.history.length - 1]); } else { this.goToBoard(); } } registerZoomChangeListener(fn) { this.zoomChangedListeners.push(fn); return () => { let idx = this.zoomChangedListeners.indexOf(fn); if (idx != -1) { this.zoomChangedListeners.splice(idx, 1); } }; } registerSelectionChangeListener(fn) { this.selectionChangeListeners.push(fn); return () => { let idx = this.selectionChangeListeners.indexOf(fn); if (idx != -1) { this.selectionChangeListeners.splice(idx, 1); } }; } zoom(selection, animate = true) { let scaleTransform; let translateTransform; let boardSelection = this.getBoard(); let boundingBox = selection.node().getBBox(); if (selection.node() !== boardSelection.node()) { if (selection != this.focusedElement) { if ((this.history.length && this.history[this.history.length - 1].node() !== selection.node()) || !this.history.length) { this.history.push(selection); } } } else { this.clearHistory(); } this.selectElements(".focused").classed("focused", false); selection.classed("focused", true); this.focusedElement = selection; let all = boardSelection.selectAll(`*`); let activeLayer = selection.selectAll(".focused > *"); let parentWidth = this.element.clientWidth; let parentHeight = this.element.clientHeight; let desiredWidth = parentWidth - this.margin * 2; let desiredHeight = parentHeight - this.margin * 2; let widthRatio = desiredWidth / boundingBox.width; let heightRatio = desiredHeight / boundingBox.height; let ratio = Math.min(widthRatio, heightRatio); scaleTransform = `scale(${ratio})`; let newX = this.element.clientWidth / 2 - boundingBox.width * ratio / 2 - boundingBox.x * ratio; let newY = this.element.clientHeight / 2 - boundingBox.height * ratio / 2 - boundingBox.y * ratio; translateTransform = `translate(${newX},${newY})`; let currentTransform = selection.attr("transform"); if (!currentTransform) { currentTransform = "translate(0, 0)scale(1)"; } if (this.config.showBehavior !== showBehavior_enum_1.ShowBehavior.All) { let hideList = this.getHideList(selection); let showList = this.getShowList(selection); hideList .style("opacity", 1) .transition() .duration(animate ? 300 : 0) .style("opacity", 0); showList .transition() .style("opacity", 0) .duration(animate ? 300 : 0) .style("opacity", 1); selection .transition() .style("opacity", 0) .duration(animate ? 300 : 0) .style("opacity", 1); console.log(selection); } boardSelection .transition() .duration(animate ? 300 : 0) .attr("transform", `${translateTransform}${scaleTransform}`); let tmpListeners = this.zoomChangedListeners.concat([]); tmpListeners.forEach(listener => { listener(); }); } getShowList(selection) { if (this.config.showBehavior === showBehavior_enum_1.ShowBehavior.AllDecendants) { return selection.selectAll(".focused *"); } else { return selection.selectAll(".focused > *"); } } getHideList(selection) { let boardSelection = this.getBoard(); let all = boardSelection.selectAll(`*`); let children; if (this.config.showBehavior === showBehavior_enum_1.ShowBehavior.AllDecendants) { children = selection.selectAll(".focused *"); } else { children = selection.selectAll(".focused > *"); } return d3.selectAll(all.nodes().filter((a) => { return (a != boardSelection.node() && a != selection.node() && children.nodes().indexOf(a) == -1 && (a.style.opacity === "" || a.style.opacity === "1")); })); } refresh() { this.zoom(this.focusedElement, false); } bindEvents() { let self = this; this.selectElements("[zoom-control]").on("click", d => { let ele = d3.event.srcElement; let expose = ele.getAttribute("zoom-control"); if (expose) { this.zoom(this.selectElement(`[zoom-target="${expose}"]`)); } }); if (this.config.allowManualSelection) { this.selectElements("[seat]").on("click", function () { let selectionsChanged = false; let ele = this; if (!ele.hasAttribute("locked")) { selectionsChanged = true; if (ele.hasAttribute("selected")) { self.selectedElements.splice(self.selectedElements.findIndex(x => x === ele), 1); ele.removeAttribute("selected"); } else { self.selectedElements.push(ele); ele.setAttribute("selected", ""); } } if (selectionsChanged) { self.emitSelectionChangeEvent(selectionChangeEvent_model_1.SelectionChangeEventReason.SelectionChanged); } }); } } lock(ele, c = "", emitEvents = true) { let selectionChanges = false; ele = this.resolveElements(ele); ele.forEach(e => { if (!e.hasAttribute("locked") || e.getAttribute("locked") != c) { e.setAttribute("locked", c); if (e.hasAttribute("selected")) { e.removeAttribute("selected"); selectionChanges = true; } } }); if (emitEvents && selectionChanges) { this.emitSelectionChangeEvent(selectionChangeEvent_model_1.SelectionChangeEventReason.LockOverride); } } unlockAll(c = "") { if (c) { this.unlock(`[locked="${c}"]`); } else { this.unlock("[locked]"); } } unlock(ele) { ele = this.resolveElements(ele); ele.forEach(e => { if (e.hasAttribute("locked")) { e.removeAttribute("locked"); } }); } deselectAll(emitEvents = true) { this.deselect("[selected]", emitEvents); } deselect(ele, emitEvents = true) { let selectionChanges = false; ele = this.resolveElements(ele); ele.forEach(e => { if (e.hasAttribute("selected")) { selectionChanges = true; e.removeAttribute("selected"); } }); if (emitEvents && selectionChanges) { this.emitSelectionChangeEvent(selectionChangeEvent_model_1.SelectionChangeEventReason.SelectionChanged); } } select(ele, emitEvents = true) { let selectionChanges = false; ele = this.resolveElements(ele); ele.forEach(e => { if (!e.hasAttribute("locked")) { if (!e.hasAttribute("selected")) { selectionChanges = true; e.setAttribute("selected", ""); } } else { throw new Error("Unable to select element because its locked " + e.outerHTML); } }); if (emitEvents && selectionChanges) { this.emitSelectionChangeEvent(selectionChangeEvent_model_1.SelectionChangeEventReason.SelectionChanged); } } getClosestSeats(seatingAreaName, numSeats, contiguous = true, scatterFallback = true) { let stage = this.selectElement("[stage]"); let seatingArea = this.selectElement(`[seating-area="${seatingAreaName}"]`); let seats = seatingArea.selectAll("[seat]").nodes(); let stageBBox = stage.node().getBBox(); let seatingAreaBBox = seatingArea.node().getBBox(); let stageCenterX = stageBBox.x + stageBBox.width / 2; let stageCenterY = stageBBox.y + stageBBox.height / 2; let seatingAreaCenterX = seatingAreaBBox.x + seatingAreaBBox.width / 2; let seatingAreaCenterY = seatingAreaBBox.y + seatingAreaBBox.height / 2; let slopeX = seatingAreaCenterX - stageCenterX; let slopeY = seatingAreaCenterY - stageCenterY; let direction; if (Math.abs(slopeX) > Math.abs(slopeY)) { direction = slopeX < 0 ? 4 : 2; } else { direction = slopeY < 0 ? 1 : 3; } let sortedSeats = seats.sort((a, b) => { let aX = Math.round(parseFloat(a.getAttribute("x"))); let aY = Math.round(parseFloat(a.getAttribute("y"))); let bX = Math.round(parseFloat(b.getAttribute("x"))); let bY = Math.round(parseFloat(b.getAttribute("y"))); switch (direction) { case 1: if (aY < bY) { return 1; } else if (aY > bY) { return -1; } else { if (aX < bX) { return 1; } else if (aX > bX) { return -1; } else { return 0; } } case 2: if (aX > bX) { return 1; } else if (aX < bX) { return -1; } else { if (aY > bY) { return 1; } else if (aY < bY) { return -1; } else { return 0; } } case 3: if (aY > bY) { return 1; } else if (aY < bY) { return -1; } else { if (aX < bX) { return 1; } else if (aX > bX) { return -1; } else { return 0; } } case 4: if (aX < bX) { return 1; } else if (aX > bX) { return -1; } else { if (aY > bY) { return 1; } else if (aY < bY) { return -1; } else { return 0; } } } }); if (contiguous) { let sections = []; let sortedSeatsCopy = sortedSeats.concat([]); let j = 0; do { j++; let br = -1; let lastSeat; for (let i = 0; i < sortedSeatsCopy.length; i++) { let seat = sortedSeatsCopy[i]; if (seat.hasAttribute("locked")) { br = i; sortedSeatsCopy.splice(i, 1); break; } else if (lastSeat) { if (direction === 1 || direction === 3) { let lsY = Math.round(parseFloat(lastSeat.getAttribute("y"))); let sY = Math.round(parseFloat(seat.getAttribute("y"))); if (lsY != sY) { br = i; break; } } else { let lsX = Math.round(parseFloat(lastSeat.getAttribute("x"))); let sX = Math.round(parseFloat(seat.getAttribute("x"))); if (lsX != sX) { br = i; break; } } } lastSeat = seat; } if (br == -1) { sections.push(sortedSeatsCopy.splice(0, sortedSeatsCopy.length)); } else { sections.push(sortedSeatsCopy.splice(0, br)); } } while (sortedSeatsCopy.length && j < 20); for (let i = 0; i < sections.length; i++) { let section = sections[i]; if (section.length >= numSeats) { return section.splice(0, numSeats); } } } if (!contiguous || scatterFallback) { return sortedSeats .filter(x => !x.hasAttribute("locked")) .splice(0, numSeats); } return []; } emitSelectionChangeEvent(r) { let tmpListeners = this.selectionChangeListeners.concat([]); tmpListeners.forEach(listener => { listener({ reason: r, selection: this.selectedElements.concat([]) }); }); } resolveElements(ele) { if (typeof ele === "string") { ele = this.selectElements(ele).nodes(); } else if (!(ele instanceof Array)) { ele = [ele]; } return ele; } static attach(element, config = D3SeatingChartDefaultConfig) { let d3s = new D3SeatingChart(element); d3s.init(config); return d3s; } } exports.D3SeatingChart = D3SeatingChart; /***/ }), /***/ 93: /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InlineStyle = ` [{@uid}] * { pointer-events: none; } [{@uid}] .focused, svg .focused > * { pointer-events: initial; } `; /***/ }), /***/ 94: /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var SelectionChangeEventReason; (function (SelectionChangeEventReason) { SelectionChangeEventReason[SelectionChangeEventReason["SelectionChanged"] = 1] = "SelectionChanged"; SelectionChangeEventReason[SelectionChangeEventReason["LockOverride"] = 2] = "LockOverride"; })(SelectionChangeEventReason = exports.SelectionChangeEventReason || (exports.SelectionChangeEventReason = {})); class SelectionChangeEvent { } exports.SelectionChangeEvent = SelectionChangeEvent; /***/ }) },[177]);