// Production steps of ECMA-262, Edition 5, 15.4.4.18 // Reference: http://es5.github.io/#x15.4.4.18 if (!Array.prototype.forEach) { Array.prototype.forEach = function(callback, thisArg) { var T, k; if (this === null) { throw new TypeError(' this is null or not defined'); } // 1. Let O be the result of calling toObject() passing the // |this| value as the argument. var O = Object(this); // 2. Let lenValue be the result of calling the Get() internal // method of O with the argument "length". // 3. Let len be toUint32(lenValue). var len = O.length >>> 0; // 4. If isCallable(callback) is false, throw a TypeError exception. // See: http://es5.github.com/#x9.11 if (typeof callback !== "function") { throw new TypeError(callback + ' is not a function'); } // 5. If thisArg was supplied, let T be thisArg; else let // T be undefined. if (arguments.length > 1) { T = thisArg; } // 6. Let k be 0 k = 0; // 7. Repeat, while k < len while (k < len) { var kValue; // a. Let Pk be ToString(k). // This is implicit for LHS operands of the in operator // b. Let kPresent be the result of calling the HasProperty // internal method of O with argument Pk. // This step can be combined with c // c. If kPresent is true, then if (k in O) { // i. Let kValue be the result of calling the Get internal // method of O with argument Pk. kValue = O[k]; // ii. Call the Call internal method of callback with T as // the this value and argument list containing kValue, k, and O. callback.call(T, kValue, k, O); } // d. Increase k by 1. k++; } // 8. return undefined }; } // Production steps of ECMA-262, Edition 5, 15.4.4.19 // Reference: http://es5.github.io/#x15.4.4.19 if (!Array.prototype.map) { Array.prototype.map = function(callback, thisArg) { var T, A, k; if (this == null) { throw new TypeError(' this is null or not defined'); } // 1. Let O be the result of calling ToObject passing the |this| // value as the argument. var O = Object(this); // 2. Let lenValue be the result of calling the Get internal // method of O with the argument "length". // 3. Let len be ToUint32(lenValue). var len = O.length >>> 0; // 4. If IsCallable(callback) is false, throw a TypeError exception. // See: http://es5.github.com/#x9.11 if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function'); } // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. if (arguments.length > 1) { T = thisArg; } // 6. Let A be a new array created as if by the expression new Array(len) // where Array is the standard built-in constructor with that name and // len is the value of len. A = new Array(len); // 7. Let k be 0 k = 0; // 8. Repeat, while k < len while (k < len) { var kValue, mappedValue; // a. Let Pk be ToString(k). // This is implicit for LHS operands of the in operator // b. Let kPresent be the result of calling the HasProperty internal // method of O with argument Pk. // This step can be combined with c // c. If kPresent is true, then if (k in O) { // i. Let kValue be the result of calling the Get internal // method of O with argument Pk. kValue = O[k]; // ii. Let mappedValue be the result of calling the Call internal // method of callback with T as the this value and argument // list containing kValue, k, and O. mappedValue = callback.call(T, kValue, k, O); // iii. Call the DefineOwnProperty internal method of A with arguments // Pk, Property Descriptor // { Value: mappedValue, // Writable: true, // Enumerable: true, // Configurable: true }, // and false. // In browsers that support Object.defineProperty, use the following: // Object.defineProperty(A, k, { // value: mappedValue, // writable: true, // enumerable: true, // configurable: true // }); // For best browser support, use the following: A[k] = mappedValue; } // d. Increase k by 1. k++; } // 9. return A return A; }; } var PagedTable = function (pagedTable) { var me = this; var source = function(pagedTable) { var sourceElems = [].slice.call(pagedTable.children).filter(function(e) { return e.hasAttribute("data-pagedtable-source"); }); if (sourceElems === null || sourceElems.length !== 1) { throw("A single data-pagedtable-source was not found"); } return JSON.parse(sourceElems[0].innerHTML); }(pagedTable); var options = function(source) { var options = typeof(source.options) !== "undefined" && source.options !== null ? source.options : {}; var columns = typeof(options.columns) !== "undefined" ? options.columns : {}; var rows = typeof(options.rows) !== "undefined" ? options.rows : {}; var positiveIntOrNull = function(value) { return parseInt(value) >= 0 ? parseInt(value) : null; }; return { pages: positiveIntOrNull(options.pages), rows: { min: positiveIntOrNull(rows.min), max: positiveIntOrNull(rows.max), total: positiveIntOrNull(rows.total) }, columns: { min: positiveIntOrNull(columns.min), max: positiveIntOrNull(columns.max), total: positiveIntOrNull(columns.total) } }; }(source); var Measurer = function() { // set some default initial values that will get adjusted in runtime me.measures = { padding: 12, character: 8, height: 15, defaults: true }; me.calculate = function(measuresCell) { if (!me.measures.defaults) return; var measuresCellStyle = window.getComputedStyle(measuresCell, null); var newPadding = parsePadding(measuresCellStyle.paddingLeft) + parsePadding(measuresCellStyle.paddingRight); var sampleString = "ABCDEFGHIJ0123456789"; var newCharacter = Math.ceil(measuresCell.clientWidth / sampleString.length); if (newPadding <= 0 || newCharacter <= 0) return; me.measures.padding = newPadding; me.measures.character = newCharacter; me.measures.height = measuresCell.clientHeight; me.measures.defaults = false; }; return me; }; var Page = function(data, options) { var me = this; var defaults = { max: 7, rows: 10 }; var totalPages = function() { return Math.ceil(data.length / me.rows); }; me.number = 0; me.max = options.pages !== null ? options.pages : defaults.max; me.visible = me.max; me.rows = options.rows.min !== null ? options.rows.min : defaults.rows; me.total = totalPages(); me.setRows = function(newRows) { me.rows = newRows; me.total = totalPages(); }; me.setPageNumber = function(newPageNumber) { if (newPageNumber < 0) newPageNumber = 0; if (newPageNumber >= me.total) newPageNumber = me.total - 1; me.number = newPageNumber; }; me.setVisiblePages = function(visiblePages) { me.visible = Math.min(me.max, visiblePages); me.setPageNumber(me.number); }; me.getVisiblePageRange = function() { var start = me.number - Math.max(Math.floor((me.visible - 1) / 2), 0); var end = me.number + Math.floor(me.visible / 2) + 1; var pageCount = me.total; if (start < 0) { var diffToStart = 0 - start; start += diffToStart; end += diffToStart; } if (end > pageCount) { var diffToEnd = end - pageCount; start -= diffToEnd; end -= diffToEnd; } start = start < 0 ? 0 : start; end = end >= pageCount ? pageCount : end; var first = false; var last = false; if (start > 0 && me.visible > 1) { start = start + 1; first = true; } if (end < pageCount && me.visible > 2) { end = end - 1; last = true; } return { first: first, start: start, end: end, last: last }; }; me.getRowStart = function() { var rowStart = page.number * page.rows; if (rowStart < 0) rowStart = 0; return rowStart; }; me.getRowEnd = function() { var rowStart = me.getRowStart(); return Math.min(rowStart + me.rows, data.length); }; me.getPaddingRows = function() { var rowStart = me.getRowStart(); var rowEnd = me.getRowEnd(); return data.length > me.rows ? me.rows - (rowEnd - rowStart) : 0; }; }; var Columns = function(data, columns, options) { var me = this; me.defaults = { min: 5 }; me.number = 0; me.visible = 0; me.total = columns.length; me.subset = []; me.padding = 0; me.min = options.columns.min !== null ? options.columns.min : me.defaults.min; me.max = options.columns.max !== null ? options.columns.max : null; me.widths = {}; var widthsLookAhead = Math.max(100, options.rows.min); var paddingColChars = 10; me.emptyNames = function() { columns.forEach(function(column) { if (columns.label !== null && columns.label !== "") return false; }); return true; }; var parsePadding = function(value) { return parseInt(value) >= 0 ? parseInt(value) : 0; }; me.calculateWidths = function(measures) { columns.forEach(function(column) { var maxChars = Math.max( column.label.toString().length, column.type.toString().length ); for (var idxRow = 0; idxRow < Math.min(widthsLookAhead, data.length); idxRow++) { maxChars = Math.max(maxChars, data[idxRow][column.name.toString()].length); } me.widths[column.name] = { // width in characters chars: maxChars, // width for the inner html columns inner: maxChars * measures.character, // width adding outer styles like padding outer: maxChars * measures.character + measures.padding }; }); }; me.getWidth = function() { var widthOuter = 0; for (var idxCol = 0; idxCol < me.subset.length; idxCol++) { var columnName = me.subset[idxCol].name; widthOuter = widthOuter + me.widths[columnName].outer; } widthOuter = widthOuter + me.padding * paddingColChars * measurer.measures.character; if (me.hasMoreLeftColumns()) { widthOuter = widthOuter + columnNavigationWidthPX + measurer.measures.padding; } if (me.hasMoreRightColumns()) { widthOuter = widthOuter + columnNavigationWidthPX + measurer.measures.padding; } return widthOuter; }; me.updateSlice = function() { if (me.number + me.visible >= me.total) me.number = me.total - me.visible; if (me.number < 0) me.number = 0; me.subset = columns.slice(me.number, Math.min(me.number + me.visible, me.total)); me.subset = me.subset.map(function(column) { Object.keys(column).forEach(function(colKey) { column[colKey] = column[colKey] === null ? "" : column[colKey].toString(); }); column.width = null; return column; }); }; me.setVisibleColumns = function(columnNumber, newVisibleColumns, paddingCount) { me.number = columnNumber; me.visible = newVisibleColumns; me.padding = paddingCount; me.updateSlice(); }; me.incColumnNumber = function(increment) { me.number = me.number + increment; }; me.setColumnNumber = function(newNumber) { me.number = newNumber; }; me.setPaddingCount = function(newPadding) { me.padding = newPadding; }; me.getPaddingCount = function() { return me.padding; }; me.hasMoreLeftColumns = function() { return me.number > 0; }; me.hasMoreRightColumns = function() { return me.number + me.visible < me.total; }; me.updateSlice(0); return me; }; var data = source.data; var page = new Page(data, options); var measurer = new Measurer(data, options); var columns = new Columns(data, source.columns, options); var table = null; var tableDiv = null; var header = null; var footer = null; var tbody = null; // Caches pagedTable.clientWidth, specially for webkit var cachedPagedTableClientWidth = null; var onChangeCallbacks = []; var clearSelection = function() { if(document.selection && document.selection.empty) { document.selection.empty(); } else if(window.getSelection) { var sel = window.getSelection(); sel.removeAllRanges(); } }; var columnNavigationWidthPX = 5; var renderColumnNavigation = function(increment, backwards) { var arrow = document.createElement("div"); arrow.setAttribute("style", "border-top: " + columnNavigationWidthPX + "px solid transparent;" + "border-bottom: " + columnNavigationWidthPX + "px solid transparent;" + "border-" + (backwards ? "right" : "left") + ": " + columnNavigationWidthPX + "px solid;"); var header = document.createElement("th"); header.appendChild(arrow); header.setAttribute("style", "cursor: pointer;" + "vertical-align: middle;" + "min-width: " + columnNavigationWidthPX + "px;" + "width: " + columnNavigationWidthPX + "px;"); header.onclick = function() { columns.incColumnNumber(backwards ? -1 : increment); me.animateColumns(backwards); renderFooter(); clearSelection(); triggerOnChange(); }; return header; }; var maxColumnWidth = function(width) { var padding = 80; var columnMax = Math.max(cachedPagedTableClientWidth - padding, 0); return parseInt(width) > 0 ? Math.min(columnMax, parseInt(width)) + "px" : columnMax + "px"; }; var clearHeader = function() { var thead = pagedTable.querySelectorAll("thead")[0]; thead.innerHTML = ""; }; var renderHeader = function(clear) { cachedPagedTableClientWidth = pagedTable.clientWidth; var fragment = document.createDocumentFragment(); header = document.createElement("tr"); fragment.appendChild(header); if (columns.number > 0) header.appendChild(renderColumnNavigation(-columns.visible, true)); columns.subset = columns.subset.map(function(columnData) { var column = document.createElement("th"); column.setAttribute("align", columnData.align); column.style.textAlign = columnData.align; column.style.maxWidth = maxColumnWidth(null); if (columnData.width) { column.style.minWidth = column.style.maxWidth = maxColumnWidth(columnData.width); } var columnName = document.createElement("div"); columnName.setAttribute("class", "pagedtable-header-name"); if (columnData.label === "") { columnName.innerHTML = " "; } else { columnName.appendChild(document.createTextNode(columnData.label)); } column.appendChild(columnName); var columnType = document.createElement("div"); columnType.setAttribute("class", "pagedtable-header-type"); if (columnData.type === "") { columnType.innerHTML = " "; } else { columnType.appendChild(document.createTextNode("<" + columnData.type + ">")); } column.appendChild(columnType); header.appendChild(column); columnData.element = column; return columnData; }); for (var idx = 0; idx < columns.getPaddingCount(); idx++) { var paddingCol = document.createElement("th"); paddingCol.setAttribute("class", "pagedtable-padding-col"); header.appendChild(paddingCol); } if (columns.number + columns.visible < columns.total) header.appendChild(renderColumnNavigation(columns.visible, false)); if (typeof(clear) == "undefined" || clear) clearHeader(); var thead = pagedTable.querySelectorAll("thead")[0]; thead.appendChild(fragment); }; me.animateColumns = function(backwards) { var thead = pagedTable.querySelectorAll("thead")[0]; var headerOld = thead.querySelectorAll("tr")[0]; var tbodyOld = table.querySelectorAll("tbody")[0]; me.fitColumns(backwards); renderHeader(false); header.style.opacity = "0"; header.style.transform = backwards ? "translateX(-30px)" : "translateX(30px)"; header.style.transition = "transform 200ms linear, opacity 200ms"; header.style.transitionDelay = "0"; renderBody(false); if (headerOld) { headerOld.style.position = "absolute"; headerOld.style.transform = "translateX(0px)"; headerOld.style.opacity = "1"; headerOld.style.transition = "transform 100ms linear, opacity 100ms"; headerOld.setAttribute("class", "pagedtable-remove-head"); if (headerOld.style.transitionEnd) { headerOld.addEventListener("transitionend", function() { var headerOldByClass = thead.querySelector(".pagedtable-remove-head"); if (headerOldByClass) thead.removeChild(headerOldByClass); }); } else { thead.removeChild(headerOld); } } if (tbodyOld) table.removeChild(tbodyOld); tbody.style.opacity = "0"; tbody.style.transition = "transform 200ms linear, opacity 200ms"; tbody.style.transitionDelay = "0ms"; // force relayout window.getComputedStyle(header).opacity; window.getComputedStyle(tbody).opacity; if (headerOld) { headerOld.style.transform = backwards ? "translateX(20px)" : "translateX(-30px)"; headerOld.style.opacity = "0"; } header.style.transform = "translateX(0px)"; header.style.opacity = "1"; tbody.style.opacity = "1"; } me.onChange = function(callback) { onChangeCallbacks.push(callback); }; var triggerOnChange = function() { onChangeCallbacks.forEach(function(onChange) { onChange(); }); }; var clearBody = function() { if (tbody) { table.removeChild(tbody); tbody = null; } }; var renderBody = function(clear) { cachedPagedTableClientWidth = pagedTable.clientWidth var fragment = document.createDocumentFragment(); var pageData = data.slice(page.getRowStart(), page.getRowEnd()); pageData.forEach(function(dataRow, idxRow) { var htmlRow = document.createElement("tr"); htmlRow.setAttribute("class", (idxRow % 2 !==0) ? "even" : "odd"); if (columns.hasMoreLeftColumns()) htmlRow.appendChild(document.createElement("td")); columns.subset.forEach(function(columnData) { var cellName = columnData.name; var dataCell = dataRow[cellName]; var htmlCell = document.createElement("td"); if (dataCell === "NA") htmlCell.setAttribute("class", "pagedtable-na-cell"); if (dataCell === "__NA__") dataCell = "NA"; var cellText = document.createTextNode(dataCell); htmlCell.appendChild(cellText); if (dataCell.length > 50) { htmlCell.setAttribute("title", dataCell); } htmlCell.setAttribute("align", columnData.align); htmlCell.style.textAlign = columnData.align; htmlCell.style.maxWidth = maxColumnWidth(null); if (columnData.width) { htmlCell.style.minWidth = htmlCell.style.maxWidth = maxColumnWidth(columnData.width); } htmlRow.appendChild(htmlCell); }); for (var idx = 0; idx < columns.getPaddingCount(); idx++) { var paddingCol = document.createElement("td"); paddingCol.setAttribute("class", "pagedtable-padding-col"); htmlRow.appendChild(paddingCol); } if (columns.hasMoreRightColumns()) htmlRow.appendChild(document.createElement("td")); fragment.appendChild(htmlRow); }); for (var idxPadding = 0; idxPadding < page.getPaddingRows(); idxPadding++) { var paddingRow = document.createElement("tr"); var paddingCellRow = document.createElement("td"); paddingCellRow.innerHTML = " "; paddingCellRow.setAttribute("colspan", "100%"); paddingRow.appendChild(paddingCellRow); fragment.appendChild(paddingRow); } if (typeof(clear) == "undefined" || clear) clearBody(); tbody = document.createElement("tbody"); tbody.appendChild(fragment); table.appendChild(tbody); }; var getLabelInfo = function() { var pageStart = page.getRowStart(); var pageEnd = page.getRowEnd(); var totalRows = data.length; var totalRowsLabel = options.rows.total ? options.rows.total : totalRows; var totalRowsLabelFormat = totalRowsLabel.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,'); var infoText = (pageStart + 1) + "-" + pageEnd + " of " + totalRowsLabelFormat + " rows"; if (totalRows < page.rows) { infoText = totalRowsLabel + " row" + (totalRows != 1 ? "s" : ""); } if (columns.total > columns.visible) { var totalColumnsLabel = options.columns.total ? options.columns.total : columns.total; infoText = infoText + " | " + (columns.number + 1) + "-" + (Math.min(columns.number + columns.visible, columns.total)) + " of " + totalColumnsLabel + " columns"; } return infoText; }; var clearFooter = function() { footer = pagedTable.querySelectorAll("div.pagedtable-footer")[0]; footer.innerHTML = ""; return footer; }; var createPageLink = function(idxPage) { var pageLink = document.createElement("a"); pageLinkClass = idxPage === page.number ? "pagedtable-index pagedtable-index-current" : "pagedtable-index"; pageLink.setAttribute("class", pageLinkClass); pageLink.setAttribute("data-page-index", idxPage); pageLink.onclick = function() { page.setPageNumber(parseInt(this.getAttribute("data-page-index"))); renderBody(); renderFooter(); triggerOnChange(); }; pageLink.appendChild(document.createTextNode(idxPage + 1)); return pageLink; } var renderFooter = function() { footer = clearFooter(); var next = document.createElement("a"); next.appendChild(document.createTextNode("Next")); next.onclick = function() { page.setPageNumber(page.number + 1); renderBody(); renderFooter(); triggerOnChange(); }; if (data.length > page.rows) footer.appendChild(next); var pageNumbers = document.createElement("div"); pageNumbers.setAttribute("class", "pagedtable-indexes"); var pageRange = page.getVisiblePageRange(); if (pageRange.first) { var pageLink = createPageLink(0); pageNumbers.appendChild(pageLink); var pageSeparator = document.createElement("div"); pageSeparator.setAttribute("class", "pagedtable-index-separator-left"); pageSeparator.appendChild(document.createTextNode("...")) pageNumbers.appendChild(pageSeparator); } for (var idxPage = pageRange.start; idxPage < pageRange.end; idxPage++) { var pageLink = createPageLink(idxPage); pageNumbers.appendChild(pageLink); } if (pageRange.last) { var pageSeparator = document.createElement("div"); pageSeparator.setAttribute("class", "pagedtable-index-separator-right"); pageSeparator.appendChild(document.createTextNode("...")) pageNumbers.appendChild(pageSeparator); var pageLink = createPageLink(page.total - 1); pageNumbers.appendChild(pageLink); } if (data.length > page.rows) footer.appendChild(pageNumbers); var previous = document.createElement("a"); previous.appendChild(document.createTextNode("Previous")); previous.onclick = function() { page.setPageNumber(page.number - 1); renderBody(); renderFooter(); triggerOnChange(); }; if (data.length > page.rows) footer.appendChild(previous); var infoLabel = document.createElement("div"); infoLabel.setAttribute("class", "pagedtable-info"); infoLabel.setAttribute("title", getLabelInfo()); infoLabel.appendChild(document.createTextNode(getLabelInfo())); footer.appendChild(infoLabel); var enabledClass = "pagedtable-index-nav"; var disabledClass = "pagedtable-index-nav pagedtable-index-nav-disabled"; previous.setAttribute("class", page.number <= 0 ? disabledClass : enabledClass); next.setAttribute("class", (page.number + 1) * page.rows >= data.length ? disabledClass : enabledClass); }; var measuresCell = null; var renderMeasures = function() { var measuresTable = document.createElement("table"); measuresTable.style.visibility = "hidden"; measuresTable.style.position = "absolute"; measuresTable.style.whiteSpace = "nowrap"; measuresTable.style.height = "auto"; measuresTable.style.width = "auto"; var measuresRow = document.createElement("tr"); measuresTable.appendChild(measuresRow); measuresCell = document.createElement("td"); var sampleString = "ABCDEFGHIJ0123456789"; measuresCell.appendChild(document.createTextNode(sampleString)); measuresRow.appendChild(measuresCell); tableDiv.appendChild(measuresTable); } me.init = function() { tableDiv = document.createElement("div"); pagedTable.appendChild(tableDiv); var pagedTableClass = data.length > 0 ? "pagedtable pagedtable-not-empty" : "pagedtable pagedtable-empty"; if (columns.total == 0 || (columns.emptyNames() && data.length == 0)) { pagedTableClass = pagedTableClass + " pagedtable-empty-columns"; } tableDiv.setAttribute("class", pagedTableClass); renderMeasures(); measurer.calculate(measuresCell); columns.calculateWidths(measurer.measures); table = document.createElement("table"); table.setAttribute("cellspacing", "0"); table.setAttribute("class", "table table-condensed"); tableDiv.appendChild(table); table.appendChild(document.createElement("thead")); var footerDiv = document.createElement("div"); footerDiv.setAttribute("class", "pagedtable-footer"); tableDiv.appendChild(footerDiv); // if the host has not yet provided horizontal space, render hidden if (tableDiv.clientWidth <= 0) { tableDiv.style.opacity = "0"; } me.render(); // retry seizing columns later if the host has not provided space function retryFit() { if (tableDiv.clientWidth <= 0) { setTimeout(retryFit, 100); } else { me.render(); triggerOnChange(); } } if (tableDiv.clientWidth <= 0) { retryFit(); } }; var registerWidths = function() { columns.subset = columns.subset.map(function(column) { column.width = columns.widths[column.name].inner; return column; }); }; var parsePadding = function(value) { return parseInt(value) >= 0 ? parseInt(value) : 0; }; me.fixedHeight = function() { return options.rows.max != null; } me.fitRows = function() { if (me.fixedHeight()) return; measurer.calculate(measuresCell); var rows = options.rows.min !== null ? options.rows.min : 0; var headerHeight = header !== null && header.offsetHeight > 0 ? header.offsetHeight : 0; var footerHeight = footer !== null && footer.offsetHeight > 0 ? footer.offsetHeight : 0; if (pagedTable.offsetHeight > 0) { var availableHeight = pagedTable.offsetHeight - headerHeight - footerHeight; rows = Math.floor((availableHeight) / measurer.measures.height); } rows = options.rows.min !== null ? Math.max(options.rows.min, rows) : rows; page.setRows(rows); } // The goal of this function is to add as many columns as possible // starting from left-to-right, when the right most limit is reached // it tries to add columns from the left as well. // // When startBackwards is true columns are added from right-to-left me.fitColumns = function(startBackwards) { measurer.calculate(measuresCell); columns.calculateWidths(measurer.measures); if (tableDiv.clientWidth > 0) { tableDiv.style.opacity = 1; } var visibleColumns = tableDiv.clientWidth <= 0 ? Math.max(columns.min, 1) : 1; var columnNumber = columns.number; var paddingCount = 0; // track a list of added columns as we build the visible ones to allow us // to remove columns when they don't fit anymore. var columnHistory = []; var lastTableHeight = 0; var backwards = startBackwards; var tableDivStyle = window.getComputedStyle(tableDiv, null); var tableDivPadding = parsePadding(tableDivStyle.paddingLeft) + parsePadding(tableDivStyle.paddingRight); var addPaddingCol = false; var currentWidth = 0; while (true) { columns.setVisibleColumns(columnNumber, visibleColumns, paddingCount); currentWidth = columns.getWidth(); if (tableDiv.clientWidth - tableDivPadding < currentWidth) { break; } columnHistory.push({ columnNumber: columnNumber, visibleColumns: visibleColumns, paddingCount: paddingCount }); if (columnHistory.length > 100) { console.error("More than 100 tries to fit columns, aborting"); break; } if (columns.max !== null && columns.visible + columns.getPaddingCount() >= columns.max) { break; } // if we run out of right-columns if (!backwards && columnNumber + columns.visible >= columns.total) { // if we started adding right-columns, try adding left-columns if (!startBackwards && columnNumber > 0) { backwards = true; } else if (columns.min === null || visibleColumns + columns.getPaddingCount() >= columns.min) { break; } else { paddingCount = paddingCount + 1; } } // if we run out of left-columns if (backwards && columnNumber == 0) { // if we started adding left-columns, try adding right-columns if (startBackwards && columnNumber + columns.visible < columns.total) { backwards = false; } else if (columns.min === null || visibleColumns + columns.getPaddingCount() >= columns.min) { break; } else { paddingCount = paddingCount + 1; } } // when moving backwards try fitting left columns first if (backwards && columnNumber > 0) { columnNumber = columnNumber - 1; } if (columnNumber + visibleColumns < columns.total) { visibleColumns = visibleColumns + 1; } } var lastRenderableColumn = { columnNumber: columnNumber, visibleColumns: visibleColumns, paddingCount: paddingCount }; if (columnHistory.length > 0) { lastRenderableColumn = columnHistory[columnHistory.length - 1]; } columns.setVisibleColumns( lastRenderableColumn.columnNumber, lastRenderableColumn.visibleColumns, lastRenderableColumn.paddingCount); if (pagedTable.offsetWidth > 0) { page.setVisiblePages(Math.max(Math.ceil(1.0 * (pagedTable.offsetWidth - 250) / 40), 2)); } registerWidths(); }; me.fit = function(startBackwards) { me.fitRows(); me.fitColumns(startBackwards); } me.render = function() { me.fitColumns(false); // render header/footer to measure height accurately renderHeader(); renderFooter(); me.fitRows(); renderBody(); // re-render footer to match new rows renderFooter(); } var resizeLastWidth = -1; var resizeLastHeight = -1; var resizeNewWidth = -1; var resizeNewHeight = -1; var resizePending = false; me.resize = function(newWidth, newHeight) { function resizeDelayed() { resizePending = false; if ( (resizeNewWidth !== resizeLastWidth) || (!me.fixedHeight() && resizeNewHeight !== resizeLastHeight) ) { resizeLastWidth = resizeNewWidth; resizeLastHeight = resizeNewHeight; setTimeout(resizeDelayed, 200); resizePending = true; } else { me.render(); triggerOnChange(); resizeLastWidth = -1; resizeLastHeight = -1; } } resizeNewWidth = newWidth; resizeNewHeight = newHeight; if (!resizePending) resizeDelayed(); }; }; var PagedTableDoc; (function (PagedTableDoc) { var allPagedTables = []; PagedTableDoc.initAll = function() { allPagedTables = []; var pagedTables = [].slice.call(document.querySelectorAll('[data-pagedtable="false"],[data-pagedtable=""]')); pagedTables.forEach(function(pagedTable, idx) { pagedTable.setAttribute("data-pagedtable", "true"); pagedTable.setAttribute("pagedtable-page", 0); pagedTable.setAttribute("class", "pagedtable-wrapper"); var pagedTableInstance = new PagedTable(pagedTable); pagedTableInstance.init(); allPagedTables.push(pagedTableInstance); }); }; PagedTableDoc.resizeAll = function() { allPagedTables.forEach(function(pagedTable) { pagedTable.render(); }); }; window.addEventListener("resize", PagedTableDoc.resizeAll); return PagedTableDoc; })(PagedTableDoc || (PagedTableDoc = {})); window.onload = function() { PagedTableDoc.initAll(); };