UNPKG

carbon-components-angular

Version:
693 lines 77.7 kB
import { EventEmitter } from "@angular/core"; import { TableHeaderItem } from "./table-header-item.class"; import { TableItem } from "./table-item.class"; import { Subject } from "rxjs"; /** * TableModel represents a data model for two-dimensional data. It's used for all things table * (table component, table toolbar, pagination, etc) * * TableModel manages its internal data integrity very well if you use the provided helper * functions for modifying rows and columns and assigning header and data in that order. * * It also provides direct access to the data so you can read and modify it. * If you change the structure of the data (by directly pushing into the arrays or otherwise), * keep in mind to keep the data structure intact. * * Header length and length of every line in the data should be equal. * * If they are not consistent, unexpected things will happen. * * Use the provided functions when in doubt. */ export class TableModel { constructor() { this.dataChange = new EventEmitter(); this.rowsSelectedChange = new EventEmitter(); this.rowsExpandedChange = new EventEmitter(); this.rowsExpandedAllChange = new EventEmitter(); this.rowsCollapsedAllChange = new EventEmitter(); /** * Gets emitted when `selectAll` is called. Emits false if all rows are deselected and true if * all rows are selected. */ this.selectAllChange = new Subject(); /** * Contains information about selection state of rows in the table. */ this.rowsSelected = []; /** * Contains information about expanded state of rows in the table. */ this.rowsExpanded = []; /** * Contains information about initial index of rows in the table */ this.rowsIndices = []; /** * Contains information about the context of the row. * * It affects styling of the row to reflect the context. * * string can be one of `"success" | "warning" | "info" | "error" | ""` and it's * empty or undefined by default */ this.rowsContext = []; /** * Contains class name(s) of the row. * * It affects styling of the row to reflect the appended class name(s). * * It's empty or undefined by default */ this.rowsClass = []; /** * Contains information about the header cells of the table. */ this.header = []; /** * Tracks the current page. */ this.currentPage = 1; /** * Length of page. */ this.pageLength = 10; /** * Set to true when there is no more data to load in the table */ this.isEnd = false; /** * Set to true when lazy loading to show loading indicator */ this.isLoading = false; /** * Used in `data` */ this._data = [[]]; /** * The number of models instantiated, this is to make sure each table has a different * model count for unique id generation. */ this.tableModelCount = 0; this.tableModelCount = TableModel.COUNT++; } /** * Sets data of the table. * * Make sure all rows are the same length to keep the column count accurate. */ set data(newData) { if (!newData || (Array.isArray(newData) && newData.length === 0)) { newData = [[]]; } this._data = newData; // init rowsSelected this.rowsSelected = new Array(this._data.length).fill(false); this.rowsExpanded = new Array(this._data.length).fill(false); // init rows indices this.rowsIndices = [...Array(this._data.length).keys()]; // init rowsContext this.rowsContext = new Array(this._data.length); // init rowsClass this.rowsClass = new Array(this._data.length); // only create a fresh header if necessary (header doesn't exist or differs in length) if (this.header == null || (this.header.length !== this._data[0].length && this._data[0].length > 0)) { let header = new Array(); for (let i = 0; i < this._data[0].length; i++) { header.push(new TableHeaderItem()); } this.header = header; } this.dataChange.emit(); } /** * Gets the full data. * * You can use it to alter individual `TableItem`s but if you need to change * table structure, use `addRow()` and/or `addColumn()` */ get data() { return this._data; } /** * Manually set data length in case the data in the table doesn't * correctly reflect all the data that table is to display. * * Example: if you have multiple pages of data that table will display * but you're loading one at a time. * * Set to `null` to reset to default behavior. */ set totalDataLength(length) { // if this function is called without a parameter we need to set to null to avoid having undefined != null this._totalDataLength = isNaN(length) ? null : length; } /** * Total length of data that table has access to, or the amount manually set */ get totalDataLength() { // if manually set data length if (this._totalDataLength !== null && this._totalDataLength >= 0) { return this._totalDataLength; } // if empty dataset if (this.data && this.data.length === 1 && this.data[0].length === 0) { return 0; } return this.data.length; } /** * Returns an id for the given column * * @param column the column to generate an id for * @param row the row of the header to generate an id for */ getId(column, row = 0) { return `table-header-${row}-${column}-${this.tableModelCount}`; } /** * Returns the id of the header. Used to link the cells with headers (or headers with headers) * * @param column the column to start getting headers for * @param colSpan the number of columns to get headers for (defaults to 1) */ getHeaderId(column, colSpan = 1) { if (column === "select" || column === "expand") { return this.getId(column); } let ids = []; for (let i = column; i >= 0; i--) { if (this.header[i]) { for (let j = 0; j < colSpan; j++) { ids.push(this.getId(i + j)); } break; } } return ids.join(" "); } /** * Finds closest header by trying the `column` and then working its way to the left * * @param column the target column */ getHeader(column) { if (!this.header) { return null; } for (let i = column; i >= 0; i--) { const headerCell = this.header[i]; if (headerCell) { return headerCell; } } return null; } /** * Returns how many rows is currently selected */ selectedRowsCount() { let count = 0; if (this.rowsSelected) { this.rowsSelected.forEach(rowSelected => { if (rowSelected) { count++; } }); } return count; } /** * Returns how many rows is currently expanded */ expandedRowsCount() { let count = 0; if (this.rowsExpanded) { this.rowsExpanded.forEach(rowExpanded => { if (rowExpanded) { count++; } }); } return count; } /** * Returns `index`th row of the table. * * Negative index starts from the end. -1 being the last element. * * @param index */ row(index) { return this.data[this.realRowIndex(index)]; } /** * Adds a row to the `index`th row or appends to table if index not provided. * * If row is shorter than other rows or not provided, it will be padded with * empty `TableItem` elements. * * If row is longer than other rows, others will be extended to match so no data is lost. * * If called on an empty table with no parameters, it creates a 1x1 table. * * Negative index starts from the end. -1 being the last element. * * @param [row] * @param [index] */ addRow(row, index) { // if table empty create table with row if (!this.data || this.data.length === 0 || this.data[0].length === 0) { let newData = new Array(); newData.push(row ? row : [new TableItem()]); // row or one empty one column row this.data = newData; return; } let realRow = row; const columnCount = this.data[0].length; if (row == null) { realRow = new Array(); for (let i = 0; i < columnCount; i++) { realRow.push(new TableItem()); } } if (realRow.length < columnCount) { // extend the length of realRow const difference = columnCount - realRow.length; for (let i = 0; i < difference; i++) { realRow.push(new TableItem()); } } else if (realRow.length > columnCount) { // extend the length of header let difference = realRow.length - this.header.length; for (let j = 0; j < difference; j++) { this.header.push(new TableHeaderItem()); } // extend the length of every other row for (let i = 0; i < this.data.length; i++) { let currentRow = this.data[i]; difference = realRow.length - currentRow.length; for (let j = 0; j < difference; j++) { currentRow.push(new TableItem()); } } } if (index == null) { this.data.push(realRow); // update rowsSelected property for length this.rowsSelected.push(false); // update rowsExpanded property for length this.rowsExpanded.push(false); // update rowsContext property for length this.rowsContext.push(undefined); // update rowsClass property for length this.rowsClass.push(undefined); // update rowsIndices property for length this.rowsIndices.push(this.data.length - 1); } else { const ri = this.realRowIndex(index); this.data.splice(ri, 0, realRow); // update rowsSelected property for length this.rowsSelected.splice(ri, 0, false); // update rowsExpanded property for length this.rowsExpanded.splice(ri, 0, false); // update rowsContext property for length this.rowsContext.splice(ri, 0, undefined); // update rowsClass property for length this.rowsClass.splice(ri, 0, undefined); // update rowsIndices property for length this.rowsIndices.splice(ri, 0, this.data.length - 1); } this.dataChange.emit(); } /** * Deletes `index`th row. * * Negative index starts from the end. -1 being the last element. * * @param index */ deleteRow(index) { const rri = this.realRowIndex(index); this.data.splice(rri, 1); this.rowsSelected.splice(rri, 1); this.rowsExpanded.splice(rri, 1); this.rowsContext.splice(rri, 1); this.rowsClass.splice(rri, 1); const rowIndex = this.rowsIndices[rri]; this.rowsIndices.splice(rri, 1); this.rowsIndices = this.rowsIndices.map((value) => (value > rowIndex) ? --value : value); this.dataChange.emit(); } /** * Deletes all rows. */ deleteAllRows() { this.data = []; } hasExpandableRows() { return this.data.some(data => data.some(d => d && d.expandedData)); // checking for some in 2D array } /** * Number of rows that can be expanded. * * @returns number */ expandableRowsCount() { return this.data.reduce((counter, _, index) => { counter = (this.isRowExpandable(index)) ? counter + 1 : counter; return counter; }, 0); } isRowExpandable(index) { return this.data[index].some(d => d && d.expandedData); } isRowExpanded(index) { return this.rowsExpanded[index]; } getRowContext(index) { return this.rowsContext[index]; } /** * Returns `index`th column of the table. * * Negative index starts from the end. -1 being the last element. * * @param index */ column(index) { let column = new Array(); const ri = this.realColumnIndex(index); const rc = this.data.length; for (let i = 0; i < rc; i++) { const row = this.data[i]; column.push(row[ri]); } return column; } /** * Adds a column to the `index`th column or appends to table if index not provided. * * If column is shorter than other columns or not provided, it will be padded with * empty `TableItem` elements. * * If column is longer than other columns, others will be extended to match so no data is lost. * * If called on an empty table with no parameters, it creates a 1x1 table. * * Negative index starts from the end. -1 being the last element. * * @param [column] * @param [index] */ addColumn(column, index) { // if table empty create table with row if (!this.data || this.data.length === 0 || this.data[0].length === 0) { let newData = new Array(); if (column == null) { newData.push([new TableItem()]); } else { for (let i = 0; i < column.length; i++) { let item = column[i]; newData.push([item]); } } this.data = newData; return; } let rc = this.data.length; // row count let ci = this.realColumnIndex(index); // append missing rows for (let i = 0; column != null && i < column.length - rc; i++) { this.addRow(); } rc = this.data.length; if (index == null) { // append to end for (let i = 0; i < rc; i++) { let row = this.data[i]; row.push(column == null || column[i] == null ? new TableItem() : column[i]); } // update header if not already set by user if (this.header.length < this.data[0].length) { this.header.push(new TableHeaderItem()); } } else { if (index >= this.data[0].length) { // if trying to append ci++; } // insert for (let i = 0; i < rc; i++) { let row = this.data[i]; row.splice(ci, 0, column == null || column[i] == null ? new TableItem() : column[i]); } // update header if not already set by user if (this.header.length < this.data[0].length) { this.header.splice(ci, 0, new TableHeaderItem()); } } this.dataChange.emit(); } /** * Deletes `index`th column. * * Negative index starts from the end. -1 being the last element. * * @param index */ deleteColumn(index) { const rci = this.realColumnIndex(index); const rowCount = this.data.length; for (let i = 0; i < rowCount; i++) { this.data[i].splice(rci, 1); } // update header if not already set by user if (this.header.length > this.data[0].length) { this.header.splice(rci, 1); } this.dataChange.emit(); } moveColumn(indexFrom, indexTo) { const headerFrom = this.header[indexFrom]; this.addColumn(this.column(indexFrom), indexTo); this.deleteColumn(indexFrom + (indexTo < indexFrom ? 1 : 0)); this.header[indexTo + (indexTo > indexFrom ? -1 : 0)] = headerFrom; } /** * cycle through the three sort states * @param index */ cycleSortState(index) { // no sort provided so do the simple sort switch (this.header[index].sortDirection) { case "ASCENDING": this.header[index].sortDirection = "DESCENDING"; break; case "DESCENDING": this.header[index].sortDirection = "NONE"; break; default: this.header[index].sortDirection = "ASCENDING"; break; } } /** * Sorts the data currently present in the model based on `compare()` * * Direction is set by `ascending` and `descending` properties of `TableHeaderItem` * in `index`th column. * * @param index The column based on which it's sorting */ sort(index) { this.pushRowStateToModelData(); const headerSorted = this.header[index].sorted; // We only allow sorting by a single column, so reset sort state for all columns before specifying new sort state this.header.forEach(column => column.sorted = false); if (this.header[index].sortDirection === "NONE" && headerSorted) { // Restore initial order of rows const oldData = this._data; this._data = []; for (let i = 0; i < this.rowsIndices.length; i++) { const ri = this.rowsIndices[i]; this._data[ri] = oldData[i]; } } else { const descending = this.header[index].sortDirection === "DESCENDING" ? -1 : 1; this.data.sort((a, b) => { return descending * this.header[index].compare(a[index], b[index]); }); this.header[index].sorted = true; } this.popRowStateFromModelData(); } /** * Appends `rowsSelected` and `rowsExpanded` info to model data. * * When sorting rows, do this first so information about row selection * gets sorted with the other row info. * * Call `popRowSelectionFromModelData()` after sorting to make everything * right with the world again. */ pushRowStateToModelData() { for (let i = 0; i < this.data.length; i++) { const rowSelectedMark = new TableItem(); rowSelectedMark.data = this.rowsSelected[i]; this.data[i].push(rowSelectedMark); const rowExpandedMark = new TableItem(); rowExpandedMark.data = this.rowsExpanded[i]; this.data[i].push(rowExpandedMark); const rowContext = new TableItem(); rowContext.data = this.rowsContext[i]; this.data[i].push(rowContext); const rowClass = new TableItem(); rowClass.data = this.rowsClass[i]; this.data[i].push(rowClass); const rowIndex = new TableItem(); rowIndex.data = this.rowsIndices[i]; this.data[i].push(rowIndex); } } /** * Restores `rowsSelected` from data pushed by `pushRowSelectionToModelData()` * * Call after sorting data (if you previously pushed to maintain selection order) * to make everything right with the world again. */ popRowStateFromModelData() { for (let i = 0; i < this.data.length; i++) { this.rowsIndices[i] = this.data[i].pop().data; this.rowsClass[i] = this.data[i].pop().data; this.rowsContext[i] = this.data[i].pop().data; this.rowsExpanded[i] = !!this.data[i].pop().data; this.rowsSelected[i] = !!this.data[i].pop().data; } } /** * Checks if row is filtered out. * * @param index * @returns true if any of the filters in header filters out the `index`th row */ isRowFiltered(index) { const realIndex = this.realRowIndex(index); return this.header.some((item, i) => item && item.filter(this.row(realIndex)[i])); } /** * Select/deselect `index`th row based on value * * @param index index of the row to select * @param value state to set the row to. Defaults to `true` */ selectRow(index, value = true) { if (this.isRowDisabled(index)) { return; } this.rowsSelected[index] = value; this.rowsSelectedChange.emit(index); } /** * Selects or deselects all rows in the model * * @param value state to set all rows to. Defaults to `true` */ selectAll(value = true) { if (this.data.length >= 1 && this.data[0].length >= 1) { for (let i = 0; i < this.rowsSelected.length; i++) { this.selectRow(i, value); } } this.selectAllChange.next(value); } isRowSelected(index) { return this.rowsSelected[index]; } /** * Checks if row is disabled or not. */ isRowDisabled(index) { const row = this.data[index]; return !!row.disabled; } /** * Expands/Collapses `index`th row based on value * * @param index index of the row to expand or collapse * @param value expanded state of the row. `true` is expanded and `false` is collapsed */ expandRow(index, value = true) { this.rowsExpanded[index] = value; this.rowsExpandedChange.emit(index); } /** * Expands / collapses all rows * * @param value expanded state of the rows. `true` is expanded and `false` is collapsed */ expandAllRows(value = true) { if (this.data.length > 0) { for (let i = 0; i < this.data.length; i++) { if (this.isRowExpandable(i)) { this.rowsExpanded[i] = value; } } if (value) { this.rowsExpandedAllChange.emit(); } else { this.rowsCollapsedAllChange.emit(); } } } /** * Gets the true index of a row based on it's relative position. * Like in Python, positive numbers start from the top and * negative numbers start from the bottom. * * @param index */ realRowIndex(index) { return this.realIndex(index, this.data.length); } /** * Gets the true index of a column based on it's relative position. * Like in Python, positive numbers start from the top and * negative numbers start from the bottom. * * @param index */ realColumnIndex(index) { return this.realIndex(index, this.data[0].length); } /** * Generic function to calculate the real index of something. * Used by `realRowIndex()` and `realColumnIndex()` * * @param index * @param length */ realIndex(index, length) { if (index == null) { return length - 1; } else if (index >= 0) { return index >= length ? length - 1 : index; } else { return -index >= length ? 0 : length + index; } } } /** * The number of models instantiated, used for (among other things) unique id generation */ TableModel.COUNT = 0; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtbW9kZWwuY2xhc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGFibGUvdGFibGUtbW9kZWwuY2xhc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUc3QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRS9DLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFJL0I7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFNLE9BQU8sVUFBVTtJQXdLdEI7UUEvSEEsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDaEMsdUJBQWtCLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUNoRCx1QkFBa0IsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBQ2hELDBCQUFxQixHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDM0MsMkJBQXNCLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUM1Qzs7O1dBR0c7UUFDSCxvQkFBZSxHQUFHLElBQUksT0FBTyxFQUFXLENBQUM7UUFZekM7O1dBRUc7UUFDSCxpQkFBWSxHQUFjLEVBQUUsQ0FBQztRQUU3Qjs7V0FFRztRQUNILGlCQUFZLEdBQWMsRUFBRSxDQUFDO1FBRTdCOztXQUVHO1FBQ0gsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFFM0I7Ozs7Ozs7V0FPRztRQUNILGdCQUFXLEdBQWEsRUFBRSxDQUFDO1FBRTNCOzs7Ozs7V0FNRztRQUNILGNBQVMsR0FBYSxFQUFFLENBQUM7UUFFekI7O1dBRUc7UUFDSCxXQUFNLEdBQXNCLEVBQUUsQ0FBQztRQUUvQjs7V0FFRztRQUNILGdCQUFXLEdBQUcsQ0FBQyxDQUFDO1FBRWhCOztXQUVHO1FBQ0gsZUFBVSxHQUFHLEVBQUUs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O0lBQ25ELENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDTyxTQUFTLENBQUMsS0FBYSxFQUFFLE1BQWM7UUFDaEQsSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFO1lBQ2xCLE9BQU8sTUFBTSxHQUFHLENBQUMsQ0FBQztTQUNsQjthQUFNLElBQUksS0FBSyxJQUFJLENBQUMsRUFBRTtZQUN0QixPQUFPLEtBQUssSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztTQUM1QzthQUFNO1lBQ04sT0FBTyxDQUFDLEtBQUssSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztTQUM3QztJQUNGLENBQUM7O0FBdHZCRDs7R0FFRztBQUNjLGdCQUFLLEdBQUcsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuaW1wb3J0IHsgUGFnaW5hdGlvbk1vZGVsIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvcGFnaW5hdGlvblwiO1xuaW1wb3J0IHsgVGFibGVIZWFkZXJJdGVtIH0gZnJvbSBcIi4vdGFibGUtaGVhZGVyLWl0ZW0uY2xhc3NcIjtcbmltcG9ydCB7IFRhYmxlSXRlbSB9IGZyb20gXCIuL3RhYmxlLWl0ZW0uY2xhc3NcIjtcbmltcG9ydCB7IFRhYmxlUm93IH0gZnJvbSBcIi4vdGFibGUtcm93LmNsYXNzXCI7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcblxuZXhwb3J0IHR5cGUgSGVhZGVyVHlwZSA9IG51bWJlciB8IFwic2VsZWN0XCIgfCBcImV4cGFuZFwiO1xuXG4vKipcbiAqIFRhYmxlTW9kZWwgcmVwcmVzZW50cyBhIGRhdGEgbW9kZWwgZm9yIHR3by1kaW1lbnNpb25hbCBkYXRhLiBJdCdzIHVzZWQgZm9yIGFsbCB0aGluZ3MgdGFibGVcbiAqICh0YWJsZSBjb21wb25lbnQsIHRhYmxlIHRvb2xiYXIsIHBhZ2luYXRpb24sIGV0YylcbiAqXG4gKiBUYWJsZU1vZGVsIG1hbmFnZXMgaXRzIGludGVybmFsIGRhdGEgaW50ZWdyaXR5IHZlcnkgd2VsbCBpZiB5b3UgdXNlIHRoZSBwcm92aWRlZCBoZWxwZXJcbiAqIGZ1bmN0aW9ucyBmb3IgbW9kaWZ5aW5nIHJvd3MgYW5kIGNvbHVtbnMgYW5kIGFzc2lnbmluZyBoZWFkZXIgYW5kIGRhdGEgaW4gdGhhdCBvcmRlci5cbiAqXG4gKiBJdCBhbHNvIHByb3ZpZGVzIGRpcmVjdCBhY2Nlc3MgdG8gdGhlIGRhdGEgc28geW91IGNhbiByZWFkIGFuZCBtb2RpZnkgaXQuXG4gKiBJZiB5b3UgY2hhbmdlIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEgKGJ5IGRpcmVjdGx5IHB1c2hpbmcgaW50byB0aGUgYXJyYXlzIG9yIG90aGVyd2lzZSksXG4gKiBrZWVwIGluIG1pbmQgdG8ga2VlcCB0aGUgZGF0YSBzdHJ1Y3R1cmUgaW50YWN0LlxuICpcbiAqIEhlYWRlciBsZW5ndGggYW5kIGxlbmd0aCBvZiBldmVyeSBsaW5lIGluIHRoZSBkYXRhIHNob3VsZCBiZSBlcXVhbC5cbiAqXG4gKiBJZiB0aGV5IGFyZSBub3QgY29uc2lzdGVudCwgdW5leHBlY3RlZCB0aGluZ3Mgd2lsbCBoYXBwZW4uXG4gKlxuICogVXNlIHRoZSBwcm92aWRlZCBmdW5jdGlvbnMgd2hlbiBpbiBkb3VidC5cbiAqL1xuZXhwb3J0IGNsYXNzIFRhYmxlTW9kZWwgaW1wbGVtZW50cyBQYWdpbmF0aW9uTW9kZWwge1xuXHQvKipcblx0ICogVGhlIG51bWJlciBvZiBtb2RlbHMgaW5zdGFudGlhdGVkLCB1c2VkIGZvciAoYW1vbmcgb3RoZXIgdGhpbmdzKSB1bmlxdWUgaWQgZ2VuZXJhdGlvblxuXHQgKi9cblx0cHJvdGVjdGVkIHN0YXRpYyBDT1VOVCA9IDA7XG5cblx0LyoqXG5cdCAqIFNldHMgZGF0YSBvZiB0aGUgdGFibGUuXG5cdCAqXG5cdCAqIE1ha2Ugc3VyZSBhbGwgcm93cyBhcmUgdGhlIHNhbWUgbGVuZ3RoIHRvIGtlZXAgdGhlIGNvbHVtbiBjb3VudCBhY2N1cmF0ZS5cblx0ICovXG5cdHNldCBkYXRhKG5ld0RhdGE6IFRhYmxlSXRlbVtdW10pIHtcblx0XHRpZiAoIW5ld0RhdGEgfHwgKEFycmF5LmlzQXJyYXkobmV3RGF0YSkgJiYgbmV3RGF0YS5sZW5ndGggPT09IDApKSB7XG5cdFx0XHRuZXdEYXRhID0gW1tdXTtcblx0XHR9XG5cblx0XHR0aGlzLl9kYXRhID0gbmV3RGF0YTtcblxuXHRcdC8vIGluaXQgcm93c1NlbGVjdGVkXG5cdFx0dGhpcy5yb3dzU2VsZWN0ZWQgPSBuZXcgQXJyYXk8Ym9vbGVhbj4odGhpcy5fZGF0YS5sZW5ndGgpLmZpbGwoZmFsc2UpO1xuXHRcdHRoaXMucm93c0V4cGFuZGVkID0gbmV3IEFycmF5PGJvb2xlYW4+KHRoaXMuX2RhdGEubGVuZ3RoKS5maWxsKGZhbHNlKTtcblx0XHQvLyBpbml0IHJvd3MgaW5kaWNlc1xuXHRcdHRoaXMucm93c0luZGljZXMgPSBbLi4uQXJyYXkodGhpcy5fZGF0YS5sZW5ndGgpLmtleXMoKV07XG5cdFx0Ly8gaW5pdCByb3dzQ29udGV4dFxuXHRcdHRoaXMucm93c0NvbnRleHQgPSBuZXcgQXJyYXk8c3RyaW5nPih0aGlzLl9kYXRhLmxlbmd0aCk7XG5cblx0XHQvLyBpbml0IHJvd3NDbGFzc1xuXHRcdHRoaXMucm93c0NsYXNzID0gbmV3IEFycmF5PHN0cmluZz4odGhpcy5f