/* JQUERY ENGINE */
/* JSPDF ENGINE */
/* KONVA ENGINE */
/* MARKJS ENGINE */
var additionalRowStorage;
if (typeof additionalRowStorage === 'undefined') {
var additionalRowStorage = {
'ELEMENT_IDS': {}
};
}
// populate all session_key fields
$('.session_key').text(sessionKey);
// just used in rail report
// rail summary has to be built first
if (typeof buildRailSummaryFromJson != 'undefined') {
buildRailSummaryFromJson();
}
if (typeof buildJsonTable != 'undefined') {
buildJsonTable(null, true);
}
// this function will clear the cache for all reports with the same uid
function clearReportCache() {
localStorage.removeItem(sessionKey);
var thisUid = sessionKey.split('/')[0];
for (var cache in localStorage) {
var uid = cache.split('/')[0];
if (thisUid == uid) {
localStorage.removeItem(cache);
}
}
}
function cacheWebPage() {
delayedExecutionOrCancel('cacheWebPage', () => {
localStorage.setItem(sessionKey, JSON.stringify(additionalRowStorage));
}, 500);
}
function loadFromCache() {
var cache = localStorage.getItem(sessionKey);
// if there is a cache we want to use that.
// the presence of a cache means the external json file (if it exists/existed)
// has already been loaded into memory for this report instance
if (cache != null) {
additionalRowStorage = JSON.parse(cache);
if (!additionalRowStorage['ELEMENT_IDS']) {
additionalRowStorage['ELEMENT_IDS'] = {};
}
}
cacheWebPage();
}
function textRegexMatchArray(text, regex) {
try {
var reg = new RegExp(regex, 'i');
return text.match(reg);
} catch {
return false;
}
}
function equalsContainsMatches(text, match) {
if (text === match) return true;
if (text.indexOf(match) > -1) return true;
return textRegexMatchArray(text, match);
}
function escapeRegex(string) {
if (!escapeRegex.regex) {
escapeRegex.regex = /[-\/\\^$*+?.()|[\]{}]/g;
}
return string.replace(escapeRegex.regex, '\\$&');
}
function getCurrentDirectory() {
// origin will be http if its on the webserver and file if its local
if (window.location.origin.match(/https?:\/\//i)) {
const ret = window.location.href.split('/').slice(0, -1).join('/');
return ret;
}
// start at index 1 because index 0 is empty meaning it adds a slash at the beginning
// and we dont want the extra slash.
// end at index -1 because the last index is the file name and we dont want that either.
var dir = window.location.pathname.split('/').slice(1, -1).join('/');
// linux directory structure fix. if the window location pathname doesnt include the drive, we add the file prefix. this fixes it in bills vm.
if (!dir.match(/^\w+:\//i)) {
dir = 'file:///' + dir;
}
return dir;
}
function moveCaretToEnd(el) {
var range = document.createRange();
range.selectNode(el);
range.setStart(el, 0);
range.setEnd(el, 1);
range.collapse();
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
function copyTextToClipboard(text) {
//Create a textbox field where we can insert text to.
var copyFrom = document.createElement("textarea");
//Set the text content to be the text you wished to copy.
copyFrom.textContent = text;
//Append the textbox field into the body as a child.
//"execCommand()" only works when there exists selected text, and the text is inside
//document.body (meaning the text is part of a valid rendered HTML element).
document.body.appendChild(copyFrom);
//Select all the text!
copyFrom.select();
//Execute command
document.execCommand('copy');
//(Optional) De-select the text using blur().
copyFrom.blur();
//Remove the textbox field from the document.body, so no other JavaScript nor
//other elements can get access to this.
document.body.removeChild(copyFrom);
}
function downloadTextToFile(text, fileName) {
var a = document.createElement("a");
var blob = new Blob([text], { type: 'application/text' });
a.href = window.URL.createObjectURL(blob);
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
function closeModal() {
$('.modal').css('display', 'none');
}
function showSettingsModal() {
if (!document.getElementById('settings_modal_button').classList.contains('disabled')) {
$('#modal_CSET').css('display', 'block');
}
}
// this will queue a delayed execution keyed to the name that is given.
// if the same name is given again, it will cancel the previous one in favor of the next one.
function delayedExecutionOrCancel(name, callback, time) {
clearTimeout(delayedExecutionOrCancel[name]);
delayedExecutionOrCancel[name] = setTimeout(callback, time);
}
// ALL report web listeners need to go in here so they can be reloaded when we reload the table data
function initializeEventListeners() {
// reset functions that have cached data
getHeaderTextFromCell.tableHeaders = undefined;
getHeaderTextFromCell.cache = undefined
getActiveRailName.netName = undefined;
col_id_from_header_name.tableHeaders = undefined;
col_id_from_header_name.cache = undefined
lastSelectedRow = null;
createTableSortFunctions();
$('.sorted-table').tablesort();
loadFromCache();
setTableRowSelectionEvents();
setRowKeys();
setEditableCellListeners(); // needs to be above loadAdditionalRowStorage
loadAdditionalRowStorage();
setTableCellHeightRestrictionEvents();
initRailSummaryStuff();
setHighlightOnClickEvents();
}
function initializeEventListeners_PostLoad() {
if (typeof initCustomContextMenu != 'undefined') {
initCustomContextMenu();
}
if (typeof initCustomRailContextMenu != 'undefined') {
initCustomRailContextMenu();
}
$('body').css("visibility", "visible");
/* we want the last thing to be the prefilter */
if (typeof setPrefilledFilter != 'undefined') {
setPrefilledFilter();
}
/* so the uri prefilter option works - needs to happen after body is visible */
if (typeof filterTable != 'undefined') {
filterTable(true);
}
}
// the idea here is the user can select either the 'All' button or one or many of the other buttons.
// pressing the 'All' button will desect all the other buttons.
// pressing any other button will select it and deselect the 'All' button if it's selected
function filterTableBy(event, type) {
// if no type is selected then
if (!type) {
$('.table-sub-filter-button').removeClass('selected');
}
else {
$('.table-sub-filter-button.default').removeClass('selected');
}
$(event.currentTarget).toggleClass('selected');
if ($('.table-sub-filter-button.selected').length == 0) {
$('.table-sub-filter-button.default').addClass('selected');
}
filterTable();
}
function filterTable(skipWait = false) {
var filterSelection = $('#table-filter-column-selection');
if (!filterSelection.length) return;
delayedExecutionOrCancel('filterTable', () => {
saveFilteredTableSearchInputs();
$('.overflow_div .sorted-table tbody').unmark();
const colName = filterSelection.children('option:selected').text();
const colIdx = col_id_from_header_name(colName);
if (colIdx < 0) return;
if (filterSelection.find(':selected').hasClass('is-number-range')) {
$('#table-filter-text-input-container').css('display', 'none');
$('#table-filter-range-input-container').css('display', '');
hideRowRange(colIdx);
}
else {
$('#table-filter-text-input-container').css('display', '');
$('#table-filter-range-input-container').css('display', 'none');
hideRows(colIdx);
}
const rowCount = $('.overflow_div .sorted-table tbody tr:visible').length;
$('#filter-search-result-text').text(rowCount);
}, skipWait ? 0 : 1000);
}
function hideRowRange(colIdx) {
var rangeLow = $('#table-filter-range-input-low');
var rangeHigh = $('#table-filter-range-input-high');
const showEdited = $('#table-sub-filter-edited').hasClass('selected');
const showVoltMissmatch = $('#table-sub-filter-volt-mismatch').hasClass('selected');
const pinVoltColumn = col_id_from_header_name('pin volt');
const netVoltColumn = col_id_from_header_name('net volt');
for (const rowEl of $('.overflow_div .sorted-table tbody tr').toArray()) {
const row = $(rowEl);
const children = row.children();
if (showEdited) {
var noEdits = true;
for (const cell of children) {
if ($(cell).hasClass('edited')) {
noEdits = false;
break;
}
}
if (noEdits) {
row.css('display', 'none');
continue;
}
}
if (showVoltMissmatch && pinVoltColumn >= 0 && netVoltColumn >= 0) {
const pinVolt = children.eq(pinVoltColumn).text().replace(/[^0-9.\-]/ig, '');
const netVolt = children.eq(netVoltColumn).text().replace(/[^0-9.\-]/ig, '');
if (!pinVolt || !netVolt || pinVolt == netVolt) {
row.css('display', 'none');
continue;
}
}
const cell = children.eq(colIdx);
const cellNumber = Number(cell.text().replace(/[^0-9.\-]/ig, ''));
if (Number.isNaN(cellNumber) || cellNumber < rangeLow.val() || cellNumber > rangeHigh.val()) {
cell.parent('tr').hide();
}
else {
cell.parent('tr').show();
}
}
}
function hideRows(colIdx) {
const filter = $('#table-filter-text-input-field').val();
const matchByContains = $('#table-filter-text-input-logic').val() === 'c';
const filterValues = filter.split(',');
const showEdited = $('#table-sub-filter-edited').hasClass('selected');
const showVoltMissmatch = $('#table-sub-filter-volt-mismatch').hasClass('selected');
const pinVoltColumn = col_id_from_header_name('pin volt');
const netVoltColumn = col_id_from_header_name('net volt');
for (const rowEl of $('.overflow_div .sorted-table tbody tr').toArray()) {
const row = $(rowEl);
const children = row.children();
if (showEdited) {
var noEdits = true;
for (const cell of children) {
if ($(cell).hasClass('edited')) {
noEdits = false;
break;
}
}
if (noEdits) {
row.css('display', 'none');
continue;
}
}
if (showVoltMissmatch && pinVoltColumn >= 0 && netVoltColumn >= 0) {
const pinVolt = children.eq(pinVoltColumn).text().replace(/[^0-9.\-]/ig, '');
const netVolt = children.eq(netVoltColumn).text().replace(/[^0-9.\-]/ig, '');
if (!pinVolt || !netVolt || pinVolt == netVolt) {
row.css('display', 'none');
continue;
}
}
// if theres no filter applied we want to show the row
if (filterValues.length == 0) {
row.css('display', '');
continue;
}
const cell = children.eq(colIdx);
const cellText = cell.text().trim();
if (matchByContains) {
for (const searchString of filterValues) {
if (equalsContainsMatches(cellText, searchString)) {
row.css('display', '');
cell.markRegExp(new RegExp(searchString, 'i'));
break;
}
else {
row.css('display', 'none');
}
}
}
else {
for (const searchString of filterValues) {
if (equalsContainsMatches(cellText, searchString)) {
row.css('display', 'none');
break;
}
else {
row.css('display', '');
}
}
}
}
}
function acceptRejectRows(rowElements, newValue, saveButtonOn = true) {
var rows = $(rowElements);
if (rows.length <= 0) return;
var arCellId = col_id_from_header_name('a/r|accept.+?reject');
var msCellId = col_id_from_header_name('match.+?score');
// if there is no accept reject row we wont have anything to edit so no point in continuing...
if (arCellId < 0) return;
var msClass, arClass, nodeClass;
if (newValue >= 100) {
msClass = 'override-good';
arClass = 'accept';
nodeClass = 'green-node';
}
else if (newValue >= 0) {
msClass = 'override-bad';
arClass = 'reject';
nodeClass = 'red-node';
}
rows.toArray().forEach(rowElement => {
var row = $(rowElement);
var rowKey = getRowKey(row);
var cells = row.children();
var arCell = $(cells[arCellId]);
var acceptRejectCellMap = getRowCellMap(rowKey, cells[arCellId]);
// clear existing values
arCell.removeClass('accept')
.removeClass('reject');
delete acceptRejectCellMap['css-class'];
delete acceptRejectCellMap['text'];
if (newValue >= 0) {
arCell.addClass(arClass);
acceptRejectCellMap['css-class'] = arClass;
}
row.find('td .highlight-on-click').toArray().forEach(element => setNodeColor(element, nodeClass));
// if no match score row, then we stop here, otherwise its an ep compare/verify report and we edit the match score
if (msCellId < 0) return;
var msCell = $(cells[msCellId]);
var matchScoreCellMap = getRowCellMap(rowKey, cells[msCellId]);
// clear existing values
msCell.removeClass('override-bad');
msCell.removeClass('override-good');
delete matchScoreCellMap['css-class'];
delete matchScoreCellMap['overrideValue'];
if (newValue >= 0) {
msCell.addClass(msClass);
matchScoreCellMap['css-class'] = msClass;
matchScoreCellMap['overrideValue'] = newValue; // this gets picked up by NetBom to be put in the Excel report
}
});
if (saveButtonOn) {
cacheWebPage();
}
}
$('body').keydown(
function (event) {
if (event.key === "Shift" || event.key === "Control" || event.key === "Alt") {
return;
}
if (event.target.id === 'table-filter-text-input-field') {
if (event.key === 'Escape') {
// $('input#table-filter-text-input-field').val('');
$('input#table-filter-text-input-field').blur();
// filterTable();
}
else if (event.key === 'ArrowUp') {
var sel = $('#table-filter-column-selection');
var optionIndex = sel[0].options.selectedIndex;
var nextIndex = optionIndex - 1;
if (nextIndex < 0) return;
sel.val(sel[0].options[nextIndex].value);
}
else if (event.key === 'ArrowDown') {
var sel = $('#table-filter-column-selection');
var optionIndex = sel[0].options.selectedIndex;
var nextIndex = optionIndex + 1;
if (nextIndex >= sel[0].options.length) return;
sel.val(sel[0].options[nextIndex].value);
}
}
if (event.target.localName !== 'body') return;
if (event.key === "ArrowUp") {
var allRows = $(".overflow_div .sorted-table tbody tr");
var selectedTableRow = $('.overflow_div .sorted-table tbody tr.selectedRow:first');
var rowToSelect;
for (var i = $(selectedTableRow).index() - 1; i < allRows.length; i--) {
if ($(allRows[i]).css('display') !== 'none') {
if (i >= 0) {
rowToSelect = allRows[i];
}
break;
}
}
if (rowToSelect) {
// deselect all rows next to the selected row
if (!event.ctrlKey && !event.shiftKey) {
deselectTableRow($(selectedTableRow).siblings());
deselectTableRow($(selectedTableRow));
}
// select our new row
selectTableRow(rowToSelect);
}
// we dont want the scroll bar to move if we are pressing arrow keys
event.preventDefault();
}
else if (event.key === "ArrowDown") {
var allRows = $(".overflow_div .sorted-table tbody tr");
var selectedTableRow = $('.overflow_div .sorted-table tbody tr.selectedRow:last');
var rowToSelect;
for (var i = $(selectedTableRow).index() + 1; i < allRows.length; i++) {
if ($(allRows[i]).css('display') !== 'none') {
if (i < allRows.length) {
rowToSelect = allRows[i];
}
break;
}
}
if (rowToSelect) {
// deselect all rows next to the selected row
if (!event.ctrlKey && !event.shiftKey) {
deselectTableRow($(selectedTableRow).siblings());
deselectTableRow($(selectedTableRow));
}
// select our new row
selectTableRow(rowToSelect);
}
// we dont want the scroll bar to move if we are pressing arrow keys
event.preventDefault();
}
else if (event.ctrlKey && !event.shiftKey && event.key !== 'Backspace') { // ctrl + key
if (event.altKey) { // ctrl + alt + key
switch (event.key.toLowerCase()) {
case 'a': // accept
var selectedTableRow = $('.overflow_div .sorted-table tbody tr.selectedRow');
acceptRejectRows(selectedTableRow, '100', true);
break;
case 'r': // reject
var selectedTableRow = $('.overflow_div .sorted-table tbody tr.selectedRow');
acceptRejectRows(selectedTableRow, '0', true);
break;
case 'c': // clear
var selectedTableRow = $('.overflow_div .sorted-table tbody tr.selectedRow');
acceptRejectRows(selectedTableRow, '-1', true);
break;
case 'enter': // accept rows and set selected row to next row
var selectedTableRow = $('.overflow_div .sorted-table tbody tr.selectedRow');
acceptRejectRows(selectedTableRow, '100', true);
// get all rows so we can use the index of the last table row
var allRows = $(".overflow_div .sorted-table tbody tr");
deselectTableRow(null);
for (var i = selectedTableRow.last().index() + 1; i < allRows.length; i++) {
if ($(allRows[i]).css('display') !== 'none') {
if (i < allRows.length) {
selectTableRow(allRows[i]);
}
break;
}
}
break;
default:
return;
}
}
else { // ctrl + key
switch (event.key.toLowerCase()) {
case 'a': // select all visible rows
var allRows = $(".overflow_div .sorted-table tbody tr:visible");
selectTableRow(allRows);
break;
case 's': // save edited rows
saveAdditionalRowStorage();
break;
case 'f': // jump to filter
$('#table-filter-text-input-field').select();
break;
default:
return;
}
}
// we dont want normal ctrl+key things to happen if we have custom ones in place
event.preventDefault();
}
else {
writeToSelectedCells(event);
}
});
function writeToSelectedCells(event) {
// we have to check against the literal 'true' because it holds true or false as a string lol
if (document.activeElement.contentEditable !== 'true') {
return;
}
var commentCellIdx = $(document.activeElement).index();
// make sure we get an index otherwise we dont want to do anything
if (commentCellIdx >= 0) {
var selectedTableRow = $('.overflow_div .sorted-table tbody tr.selectedRow');
// we return if the selected rows are 1 because if that is the case we let the parent function take care of writing, we dont need to bulk write a single row
if (selectedTableRow.length <= 1) return 0;
if (event.key.length === 1) { // regular characters
selectedTableRow.toArray().forEach(row => {
var commentCell = $(row).children()[commentCellIdx];
$(commentCell).text($(commentCell).text() + event.key);
userCellEditCallback(commentCell);
});
} else if (event.key === 'Backspace') {
if (event.ctrlKey) { // delete word by word
selectedTableRow.toArray().forEach(row => {
var commentCell = $(row).children()[commentCellIdx];
var txt = $(commentCell).text();
$(commentCell).text(txt.substring(0, txt.lastIndexOf(' ')));
userCellEditCallback(commentCell);
});
}
else {
selectedTableRow.toArray().forEach(row => {
var commentCell = $(row).children()[commentCellIdx];
var txt = $(commentCell).text();
$(commentCell).text(txt.substring(0, txt.length - 1));
userCellEditCallback(commentCell);
});
}
}
}
return commentCellIdx >= 0;
}
/*
A simple, lightweight jQuery plugin for creating sortable tables.
https://github.com/kylefox/jquery-tablesort
Version 0.0.11
*/
function createTableSortFunctions() {
(function ($) {
$.tablesort = function ($table, settings) {
var self = this;
this.$table = $table;
this.$thead = this.$table.find('thead');
this.settings = $.extend({}, $.tablesort.defaults, settings);
this.$sortCells = this.$thead.length > 0 ? this.$thead.find('th:not(.no-sort)') : this.$table.find('th:not(.no-sort)');
this.$sortCells.on('dblclick.tablesort', function () {
self.sort($(this));
});
this.index = null;
this.$th = null;
this.direction = null;
this.sorting = false;
this.firstSort = true;
self.sort($(this.$sortCells[0]));
};
$.tablesort.prototype = {
sort: function (th, direction) {
if (this.sorting) return;
this.sorting = true;
//click on a different column
if (this.index !== th.index()) {
this.direction = 'asc';
this.index = th.index();
}
else if (direction !== 'asc' && direction !== 'desc')
this.direction = this.direction === 'asc' ? 'desc' : 'asc';
else
this.direction = direction;
direction = this.direction == 'asc' ? 1 : -1;
if (this.firstSort) {
this.sorting = false;
this.firstSort = false;
return;
}
var start = new Date(),
self = this,
table = this.$table,
rowsContainer = table.find('tbody').length > 0 ? table.find('tbody') : table,
rows = rowsContainer.find('tr'), // .has('td, th') <--- this slows things down tremendously
cells = rows.find(':nth-child(' + (th.index() + 1) + ')').filter('td, th'),
sortBy = th.data().sortBy,
sortedMap = [];
var unsortedValues = cells.map(function (idx, cell) {
if (sortBy)
return (typeof sortBy === 'function') ? sortBy($(th), $(cell), self) : sortBy;
return ($(this).data().sortValue != null ? $(this).data().sortValue : $(this).text());
});
if (unsortedValues.length === 0) {
this.sorting = false;
return;
}
self.$table.trigger('tablesort:start', [self]);
self.log("Sorting by " + this.index + ' ' + this.direction);
// Try to force a browser redraw
self.$table.css("display");
// Run sorting asynchronously on a timeout to force browser redraw after
// `tablesort:start` callback. Also avoids locking up the browser too much.
setTimeout(function () {
self.$sortCells.removeClass(self.settings.asc + ' ' + self.settings.desc);
for (var i = 0, length = unsortedValues.length; i < length; i++) {
sortedMap.push({
index: i,
cell: cells[i],
row: rows[i],
value: unsortedValues[i]
});
}
var sorter = new Intl.Collator('en', { sensitivity: 'base', numeric: true });
sortedMap.sort(function (a, b) {
// should be fastest javascript compare function
return sorter.compare(a.value, b.value) * direction;
return a.value.localeCompare(b.value, undefined, {
numeric: true,
sensitivity: 'base'
}) * direction;
return self.settings.compare(a.value, b.value) * direction;
});
$.each(sortedMap, function (i, entry) {
rowsContainer.append(entry.row);
});
th.addClass(self.settings[self.direction]);
self.sorting = false;
self.log('Sort finished in ' + ((new Date()).getTime() - start.getTime()) + 'ms');
self.$table.trigger('tablesort:complete', [self]);
//Try to force a browser redraw
self.$table.css("display");
}, unsortedValues.length > 2000 ? 200 : 10);
},
log: function (msg) {
if (($.tablesort.DEBUG || this.settings.debug) && console && console.log) {
console.log('[tablesort] ' + msg);
}
},
destroy: function () {
this.$sortCells.off('dblclick.tablesort');
this.$table.data('tablesort', null);
return null;
}
};
$.tablesort.DEBUG = false;
$.tablesort.defaults = {
debug: $.tablesort.DEBUG,
asc: 'sorted ascending',
desc: 'sorted descending',
compare: function (a, b) {
if (a > b) {
return 1;
} else if (a < b) {
return -1;
} else {
return 0;
}
}
};
$.fn.tablesort = function (settings) {
var table, sortable, previous;
return this.each(function () {
table = $(this);
previous = table.data('tablesort');
if (previous) {
previous.destroy();
}
table.data('tablesort', new $.tablesort(table, settings));
});
};
})(window.Zepto || window.jQuery);
}
// reference to jquery row object
var lastSelectedRow = null;
function selectTableRow(r) {
var row = $(r);
if (row.css("display") !== "none") {
row.addClass('selectedRow');
lastSelectedRow = row.last();
}
}
function deselectTableRow(r) {
var row = r ? $(r) : $('.selectedRow');
row.removeClass('selectedRow');
lastSelectedRow = row.last();
}
function setTableRowSelectionEvents() {
$(".sorted-table tbody tr").click(function (event) {
if (!event.ctrlKey && !event.shiftKey) {
deselectTableRow($(this).siblings());
}
if (!event.shiftKey || (event.shiftKey && !lastSelectedRow.length)) {
if ($(this).hasClass('selectedRow')) {
deselectTableRow(this);
} else {
selectTableRow(this);
}
}
else {
// order the two selected indexes
var [low, high] = [lastSelectedRow.index() + 1, this.rowIndex].sort((a, b) => a - b);
var rows = $(".sorted-table tr").filter(idx => idx <= high && idx >= low);
selectTableRow(rows);
window.getSelection().removeAllRanges(); // remove text selection that happens when a user shift clicks
}
});
}
["keyup", "keydown"].forEach((event) => {
window.addEventListener(event, (e) => {
document.onselectstart = function () {
return !(e.key == "Shift" && e.shiftKey);
}
});
});
function col_id_from_header_name(name) {
// we cache return values because theres a lot of repetitive text processing happening
if (col_id_from_header_name.cache == undefined) {
col_id_from_header_name.cache = {};
col_id_from_header_name.tableHeaders = $('.overflow_div .sorted-table thead tr th').toArray();
}
if (col_id_from_header_name.cache[name]) {
return col_id_from_header_name.cache[name];
}
var rowId = -1;
col_id_from_header_name.tableHeaders.every(h => {
var header = $(h);
// split on html tags that arent line breaks ( ) so it doesnt match the items in drop-down menus in the headers
if (equalsContainsMatches(header.html().split(/<[^<>]{3,}>/i)[0].trim().replace(/\n| /ig, ''), name)) {
rowId = header.index();
return false; // break out of loop
}
return true; // continue loop
});
col_id_from_header_name.cache[name] = rowId;
return rowId;
}
function getHeaderTextFromCell(cell) {
var index = $(cell).index();
// we cache return values because theres a lot of repetitive text processing happening
if (getHeaderTextFromCell.cache == undefined) {
getHeaderTextFromCell.cache = {};
getHeaderTextFromCell.tableHeaders = $('.overflow_div .sorted-table thead tr th').toArray();
}
if (getHeaderTextFromCell.cache[index]) {
return getHeaderTextFromCell.cache[index];
}
// need to trim because the ::after css attribute that adds the sorting arrow adds a space which messes with our dictionary keys
var ret = $(getHeaderTextFromCell.tableHeaders[index].firstChild).text().trim();
getHeaderTextFromCell.cache[index] = ret;
return ret;
}
// this needs to happen before any data is loaded
function setRowKeys() {
const rowKeyHeaderIndexes = [];
const tableHeaders = $('.sorted-table thead tr th').toArray();
for (var i = 0; i < tableHeaders.length; i++) {
if (!$(tableHeaders[i]).text().match(/accept(.+)reject|a\/r|comment/i)) {
rowKeyHeaderIndexes.push(i);
}
}
// assign row keys so they dont change when we edit cells
$('.sorted-table tbody tr').toArray().forEach(row => {
var tds = $(row).find('td');
var keyVals = [];
tds.toArray().forEach(row => {
var i = row.cellIndex;
if (rowKeyHeaderIndexes.includes(i)) {
keyVals.push($(tds[i]).text());
}
});
var key = keyVals.sort().join('').replace(/\n|\s/ig, '').toUpperCase();
row['ROW_KEY'] = key;
});
}
function getRowKey(row) { // should be a reference to the tr
return $(row)[0]['ROW_KEY'];
}
// TODO make this more versatile and usable on the table that contains the 'cell' variable instead of a hard coded table reference
function setFocusCellBelow(cell) {
var selectedTableRow = $(cell).parent();
var headerName = getHeaderTextFromCell(cell);
// get all rows so we can use the index of the last table row
var allRows = $(".overflow_div .sorted-table tbody tr");
for (var i = selectedTableRow.last().index() + 1; i < allRows.length; i++) {
if ($(allRows[i]).css('display') !== 'none') {
if (i < allRows.length) {
document.activeElement.blur();
deselectTableRow();
selectTableRow(allRows[i]);
var cellBelow = allRows[i].cells[col_id_from_header_name(headerName)];
$(cellBelow).focus();
moveCaretToEnd(cellBelow);
}
return;
}
}
}
// TODO make this more versatile and usable on the table that contains the 'cell' variable instead of a hard coded table reference
function setFocusCellAbove(cell) {
var selectedTableRow = $(cell).parent();
var headerName = getHeaderTextFromCell(cell);
// get all rows so we can use the index of the last table row
var allRows = $(".overflow_div .sorted-table tbody tr");
for (var i = selectedTableRow.last().index() - 1; i < allRows.length; i--) {
if ($(allRows[i]).css('display') !== 'none') {
if (i < allRows.length) {
document.activeElement.blur();
deselectTableRow();
selectTableRow(allRows[i]);
var cellAbove = allRows[i].cells[col_id_from_header_name(headerName)];
$(cellAbove).focus();
moveCaretToEnd(cellAbove);
}
return;
}
}
}
function setEditableCellListeners() {
$(".sorted-table tbody tr td").toArray().forEach(cellEl => {
if (cellEl.contentEditable != 'true') return;
var cell = $(cellEl);
// when overrides are loaded we want to first revert the original text so we
// store it in the cells
cell[0]['ORIGINAL_TEXT'] = cell.text().trim();
// we are trimming the text to remove the trailing whitespace which makes it more annoying to edit fields because
// they look like they end at the word but theyre annoyingly padded sometimes
cell.text(cell.text().trim());
cell.on('keyup', (event) => {
// this returns a zero if it didnt write to any cells -- basically means there are no selected rows
if (!writeToSelectedCells(event)) {
userCellEditCallback(cell);
restyle_from_derating();
}
});
});
}
function userCellEditCallback(cell) {
var jCell = $(cell);
var rowKey = getRowKey(jCell.parent());
var cellMap = getRowCellMap(rowKey, cell);
cellMap['text'] = jCell.text();
if (jCell.text() == jCell[0]['ORIGINAL_TEXT']) {
cellMap['css-class'] = '';
jCell.removeClass('edited');
}
else {
cellMap['css-class'] = 'edited';
jCell.addClass('edited');
}
cacheWebPage();
}
function saveAdditionalRowStorage() {
var reportUid = sessionKey.split('/')[0];
var toSave = {};
for (var key in localStorage) {
if (key.startsWith(reportUid)) {
var reportName = key.split('/')[1];
toSave[reportName] = localStorage.getItem(key);
}
}
var a = document.createElement("a");
var blob = new Blob(["var additionalRowStorage = " + JSON.stringify(toSave, null, 2)], { type: 'application/json' });
a.href = window.URL.createObjectURL(blob);
a.download = jsonSaveFileName;
a.click();
}
/* this needs to be called at the very end of the document load so that the row keys can be established first */
function loadAdditionalRowStorage(manualMatchScoreMap) {
if (manualMatchScoreMap != undefined) {
// reset original values before we overwrite them again
$('.overflow_div .sorted-table tbody tr td')
.toArray()
.forEach(cell => {
var cellRef = $(cell);
cellRef.removeClass('override-bad');
cellRef.removeClass('override-good');
cellRef.removeClass('accept');
cellRef.removeClass('reject');
if (cellRef[0]['ORIGINAL_TEXT']) {
cellRef.text(cellRef[0]['ORIGINAL_TEXT']);
}
});
$('.highlight-on-click.highlighted').removeClass('highlighted');
var reportUid = sessionKey.split('/')[0];
for (var reportName in manualMatchScoreMap) {
localStorage.setItem(reportUid + '/' + reportName, manualMatchScoreMap[reportName]);
}
loadFromCache();
}
try {
if (additionalRowStorage['ELEMENT_IDS']) {
for (var key in additionalRowStorage['ELEMENT_IDS']) {
var info = additionalRowStorage['ELEMENT_IDS'][key];
if (info['text']) {
$(key).text(info['text']);
}
if (info['css-class']) {
$(key).addClass(info['css-class']);
}
}
}
$('.overflow_div .sorted-table tbody tr').toArray().forEach(row => {
var rowKey = getRowKey(row);
if (additionalRowStorage[rowKey]) {
var cells = $(row).children();
for (var header in additionalRowStorage[rowKey]) {
var columnId = col_id_from_header_name(header);
if (columnId < 0) {
console.warn('Unable to find column for table header: ' + header);
continue;
}
if (additionalRowStorage[rowKey][header]['text']) {
$(cells[columnId]).text(additionalRowStorage[rowKey][header]['text']);
}
if (additionalRowStorage[rowKey][header]['css-class']) {
$(cells[columnId]).addClass(additionalRowStorage[rowKey][header]['css-class']);
}
if (additionalRowStorage[rowKey][header]['highlighted']) {
$(cells[columnId]).find('.highlight-on-click')
.toArray()
.forEach(n => {
var node = $(n);
var color = additionalRowStorage[rowKey][header]['highlighted'][node.text()];
if (color) {
node.addClass('highlighted').addClass(color);
}
});
}
}
}
});
if (getActiveRailName() != null) {
restyle_from_derating(true);
recalculateSummaryCapacitance(); // has to be after the cap_derating_change call
}
}
catch (e) {
console.log('Failed to load match score override values.');
console.log(e);
}
if (manualMatchScoreMap && window.parent) {
window.parent.postMessage({
'reload_from_cache': manualMatchScoreMap,
'location': window.location.href,
}, '*');
}
}
function overloadAdditionalRowStorage() {
// from: https://stackoverflow.com/questions/6711002/how-can-i-get-javascript-to-read-from-a-json-file
var input = document.createElement('input');
input.type = 'file';
input.onchange = e => {
// getting a hold of the file reference
var file = e.target.files[0];
// setting up the reader
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
// here we tell the reader what to do when it's done reading...
reader.onload = readerEvent => {
var content = readerEvent.target.result; // this is the content!
// we add this line so its javascript when we save to file -- we need to remove to parse as json
content = content.replace(/^var additionalRowStorage =/i, '');
var jsonobj = JSON.parse(content);
loadAdditionalRowStorage(jsonobj);
}
}
input.click();
}
function getRowCellMap(rowKey, cell) {
var cellKey = getHeaderTextFromCell(cell);
var rowMap, cellMap;
if (!additionalRowStorage[rowKey]) {
rowMap = {};
additionalRowStorage[rowKey] = rowMap;
} else {
rowMap = additionalRowStorage[rowKey];
}
if (!rowMap[cellKey]) {
cellMap = {};
rowMap[cellKey] = cellMap;
} else {
cellMap = rowMap[cellKey];
}
return cellMap;
}
function setTableCellHeightRestrictionEvents() {
var cellsToEdit = [];
$('.table-cell-height-restriction').toArray().forEach(el => {
// this means its cut off by height restriction
if (el.scrollHeight > el.clientHeight) {
cellsToEdit.push(el);
}
});
cellsToEdit.forEach(element => {
var floatingContainer = $('
');
floatingContainer.addClass('floating-table-buttons');
var jumpToTopButton = $('');
jumpToTopButton.text(" \u2191 ")
// the first css gives it its style, the second one is used to differentiate it from the other buttons
// but since we pass a reference to the click event callback we dont even need to differentiate it
.addClass('expand-icon-btn-styling')
.addClass('jump-icon-btn')
.click(e => {
e.stopPropagation();
// using a jquery accessor here instead of walking up the dom because the structure often changes
var scrollWindow = $('.overflow_div .sorted-table').get(0); // .get() returns the dom element instead of a jquery object like .first()
element.scrollIntoView({ behavior: "auto", block: "start", inline: "nearest" });
scrollWindow.scrollTo(0, scrollWindow.scrollTop - 60); // move 60 pixels above to offset header and give some margin
onResizeWindow();
});
var expandCollapsedRowButton = $('');
expandCollapsedRowButton.text(" \u21F2 ")
.addClass('expand-icon-btn-styling')
.addClass('expand-icon-btn')
.click(e => {
e.stopPropagation();
// closest will traverse up and grab the first matching thing
var row = $(e.target).closest('tr').first();
// we want to grab all the elements in all the cells of this row
var allCellsInRow = row.find('.table-cell-height-restriction');
var allContainersInRow = row.find('.floating-table-buttons');
var importantRowNames = row.find('.important-sticky-left');
var importantRowNameTds = [];
$.each(importantRowNames, function (i, importantRowInnerCell) {
importantRowNameTds.push(importantRowInnerCell.closest('td'));
});
var allExpandButtonsInRow = row.find('.expand-icon-btn');
var allJumpButtonsInRow = row.find('.jump-icon-btn');
var closestTable = $(e.target).closest('table');
var firstHeader = null;
var firstOverflowDiv = null;
if (closestTable) {
firstHeader = closestTable.find('th').first();
firstOverflowDiv = closestTable.closest('.overflow_div');
}
allCellsInRow.toggleClass('expanded');
allContainersInRow.toggleClass('expanded');
if (allCellsInRow.hasClass('expanded')) {
allExpandButtonsInRow.text(" \u21F1 ");
allJumpButtonsInRow.css("visibility", "visible");
allContainersInRow.css("top", firstHeader.outerHeight() + 1); // height of header plus 1 pixel for distancing
importantRowNames.css("top", firstOverflowDiv.outerHeight() / 2); // height of table, divided by 2
$.each(importantRowNameTds, function (i, td) {
$(td).attr('valign',"TOP");
});
}
else {
allExpandButtonsInRow.text(" \u21F2 ");
allJumpButtonsInRow.css("visibility", "hidden");
element.scrollIntoView({ behavior: "auto", block: "center", inline: "nearest" });
allContainersInRow.css("top", 0);
importantRowNames.css("top", 0);
$.each(importantRowNameTds, function (i, td) {
$(td).attr('valign',null);
});
}
onResizeWindow();
});
floatingContainer.append(expandCollapsedRowButton);
floatingContainer.append(jumpToTopButton);
// add our button container to the top of the cell container
$(element).prepend(floatingContainer);
$(element).closest('td').addClass('with-expand-icon');
});
}
function saveFilteredTableSearchInputs() {
/* var filter = $('#table-filter-text-input-field');
var rangeLow = $('#table-filter-range-input-low');
var rangeHigh = $('#table-filter-range-input-high');
var matchCriteria = $('#table-filter-text-input-logic');
sessionStorage.setItem('#table-filter-text-input-field', filter.val());
sessionStorage.setItem('#table-filter-range-input-low', rangeLow.val());
sessionStorage.setItem('#table-filter-range-input-high', rangeHigh.val());
sessionStorage.setItem('#table-filter-text-input-logic', matchCriteria.val()); */
var filterSelection = $('#table-filter-column-selection');
var filterColumnText = filterSelection[0].selectedOptions[0].textContent;
sessionStorage.setItem('#table-filter-column-selection', filterColumnText);
}
function loadFilteredTableSearchInputs() {
/* var filter = sessionStorage.getItem('#table-filter-text-input-field');
var rangeLow = sessionStorage.getItem('#table-filter-range-input-low');
var rangeHigh = sessionStorage.getItem('#table-filter-range-input-high');
var matchCriteria = sessionStorage.getItem('#table-filter-text-input-logic');
if (filter) {
$('#table-filter-text-input-field').val(filter);
}
if (rangeLow) {
$('#table-filter-range-input-low').val(rangeLow);
}
if (rangeHigh) {
$('#table-filter-range-input-high').val(rangeHigh);
}
if (matchCriteria) {
$('#table-filter-text-input-logic').val(matchCriteria);
} */
var filterSelection = sessionStorage.getItem('#table-filter-column-selection');
if (filterSelection && $('#table-filter-column-selection').length > 0) {
for (var option of $('#table-filter-column-selection')[0]) {
if (filterSelection == option.textContent) {
$('#table-filter-column-selection').val($(option).val());
break;
}
}
}
}
// https://html-online.com/articles/get-url-parameters-javascript/
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
vars[key] = value;
});
return vars;
}
// https://html-online.com/articles/get-url-parameters-javascript/
function getUrlParam(parameter, defaultvalue) {
var urlparameter = defaultvalue;
if (window.location.href.indexOf(parameter) > -1) {
urlparameter = getUrlVars()[parameter];
}
return urlparameter;
}
function setPrefilledFilter() {
var vars = getUrlVars();
if (vars.net_trace_net && vars.net_trace_table) {
const netTraceNet = decodeURIComponent(vars.net_trace_net);
const netTraceTable = decodeURIComponent(vars.net_trace_table);
this.reportName = decodeURIComponent(vars.report_name);
if (netTraceTable.match(/new/i)) {
document.title = 'New Net Trace: ' + netTraceNet;
} else if (netTraceTable.match(/old/i)) {
document.title = 'Old Net Trace: ' + netTraceNet;
} else {
document.title = 'Net Trace: ' + netTraceNet;
}
setBodyKonvaNetTrace(netTraceTable, netTraceNet);
return;
}
if (vars['table_only']) {
$('.accordion_header').css('display', 'none');
$('.nl_header_text').css('display', 'none');
$('.nl_header_button_column').css('display', 'none');
$('.sheet-change-dropdown').css('display', 'none');
$('.nl_header_logo').css('display', 'none');
$('.nl_header_wrapper').css(
{
'box-shadow': 'none', // remove box shadow
'border-top': 'none', // remove border
'padding': 0, // remove padding
'height': 0, // remove forced height
});
var html = '';
$('.nl_header_right_button_row').first().prepend(html);
$('.nl_header_right_button_row').last().css('display', 'none');
$('.nl_header_right_button_container').css('margin-top', '10px');
// set external window button event
$('#button_open_in_ex_win').click((e) => { window.open(window.location.pathname) });
$('.octopart-button').detach().prependTo($('#button_open_in_ex_win').parent());
}
if (vars['custom_title']) {
var title = vars['custom_title'].replace(/__/g, ' ');
$('#download-excel-btn').after('
' + title + '
');
}
if (vars['prefilter']) {
var filterInfo = vars['prefilter'].split(':');
var column = filterInfo[0];
var filterVal = decodeURIComponent(filterInfo[1]);
filterVal = escapeRegex(filterVal);
if (vars['prefiltertype'] === 'equals') {
filterVal = '^' + filterVal + '$';
}
column = column.replace(/_/g, ' ').toUpperCase();
var desiredColumnName = '';
for (var option of $('#table-filter-column-selection')[0]) {
if (option.textContent.toUpperCase() == column) {
desiredColumnName = $(option).val();
break;
}
}
if (desiredColumnName) {
$('#table-filter-column-selection').val(desiredColumnName);
}
$('#table-filter-text-input-field').val(filterVal);
} else {
loadFilteredTableSearchInputs();
}
}
// handler for clicking anywhere in the page
$(this).click(function (event) {
// disable all context menus
$(".context-menu").css('display', 'none');
});
function ctxmenu_init_subgroup_empty(id) {
var divId = "#" + id;
var sgId = "#" + id + '-sg';
var spl = divId.split('-');
spl.pop();
var divSectionToClose = spl.join('-');
$(sgId).hover(
function (e) { // handler in
// we only care about the mouseenter event
if (e.handleObj.origType === 'mouseleave') return;
// close all other sub groups
$(divSectionToClose + " .context-menu").css('display', 'none');
}
);
}
function ctxmenu_init_subgroup_items(id) {
var divId = "#" + id;
var sgId = "#" + id + '-sg';
var spl = divId.split('-');
spl.pop();
var divSectionToClose = spl.join('-');
$(sgId).hover(
function (e) { // handler in
// we only care about the mouseenter event
if (e.handleObj.origType === 'mouseleave') return;
// close all other sub groups
$(divSectionToClose + " .context-menu").css('display', 'none');
var parentWidth = $(divId).width();
var top = e.target.offsetTop ? e.target.offsetTop : top;
var left = parentWidth;
$(divId).css('display', 'none');
$(divId)
.toggle()
.css(
{
display: 'block',
top: top + "px",
left: left + "px"
}
);
}
);
}
function makeTclReadableMarker(allMarkerData) {
var markerText = '';
for (var rowInfo of allMarkerData) {
var topLevel = '';
for (var rowKey in rowInfo) {
if (rowKey === 'markerData') continue;
topLevel += rowKey + ':' + rowInfo[rowKey] + '\n';
}
for (var markerEntry of rowInfo.markerData) {
for (var markerMap of markerEntry) {
markerText += markerMap.use_case.toUpperCase() + '=';
if (markerMap[markerMap.use_case] != undefined) {
markerText += markerMap[markerMap.use_case];
} else {
markerText += 'UNKNOWN';
}
markerText += '\n';
markerText += topLevel;
for (var key in markerMap) {
markerText += key.toUpperCase() + ':' + markerMap[key] + '\n';
}
markerText += '\n';
}
}
}
return markerText;
}
function generateMarkerText(allMarkerData) {
var markerFile = [];
markerFile.push("(marker_file");
markerFile.push(" (version 1.0)");
markerFile.push(" (markers");
var markerCount = 1;
for (var rowInfo of allMarkerData) {
var reportColumn = rowInfo.reportColumn;
reportColumn = reportColumn[0].toUpperCase() + reportColumn.substring(1);
for (var markerData of rowInfo.markerData) {
for (var marker of markerData) {
markerFile.push(" (");
var longMsg = 'Report= ' + reportName;
longMsg += '\n Block= ' + marker.block;
longMsg += '\n Report= ' + reportColumn;
longMsg += '\n Instance= ' + marker.page_instance;
longMsg += '\n PhysicalPath= ' + marker.phys_path;
longMsg += '\n LogicalPath= ' + marker.path;
markerFile.push(' (tool "CheckPlus")');
markerFile.push(' (class "LOGICAL")');
markerFile.push(" (severity 30)");
markerFile.push(" (error_num " + markerCount++ + ")");
if (marker.use_case === 'refdes') {
var shortMsg = reportName + ' ' + marker.refdes + ' -> ' + marker.description;
markerFile.push(' (short_msg "' + shortMsg + '")');
markerFile.push(' (long_msg "' + longMsg + '")');
markerFile.push(" (location");
markerFile.push(" (");
markerFile.push(' (object_kind "instance")');
markerFile.push(' (canonical_name "_!drawerror inst ' + marker.page_instance + ';")');
markerFile.push(' (parent_canonical_name "DRAWERROR inst ' + marker.page_instance + ';")');
} else if (marker.use_case === 'node') {
var shortMsg = reportName + ' ' + marker.node_name + ' -> ' + marker.net_name;
markerFile.push(' (short_msg "' + shortMsg + '")');
markerFile.push(' (long_msg "' + longMsg + '")');
markerFile.push(" (location");
markerFile.push(" (");
markerFile.push(' (object_kind "instance_port")');
markerFile.push(' (canonical_name "_!drawerror pin ' + marker.page_instance + "." + marker.pin_name + ';")');
markerFile.push(' (parent_canonical_name "DRAWERROR pin ' + marker.page_instance + ';")');
}
markerFile.push(' (drawing_name "' + marker.path + '")');
markerFile.push(" )");
markerFile.push(" )");
markerFile.push(" )");
}
}
}
markerFile.push(" )");
markerFile.push(")");
return markerFile.join('\n');
}
function makeAllegroPcbList(rows, columnName) {
if (rows.length <= 0) return;
const cellId = col_id_from_header_name(columnName);
var markers = [];
rows.toArray().forEach(rowEl => {
const row = $(rowEl);
const cell = row.find('td').eq(cellId);
const nodeList = [];
const refdesList = [];
cell.find('.marker-data-node')
.toArray()
.forEach(cellEl => {
const cellRef = $(cellEl);
nodeList.push(cellRef.text().replace(/\n/g, '').trim());
});
cell.find('.marker-data-refdes')
.toArray()
.forEach(cellEl => {
const cellRef = $(cellEl);
refdesList.push(cellRef.text().replace(/\n/g, '').trim());
});
markers = markers.concat(nodeList, refdesList);
});
return markers.join("\n");
}
function makeMarkerFiles(rows, lookupTable, columnName) {
if (rows.length <= 0) return;
const cellId = col_id_from_header_name(columnName);
var markers = [];
rows.toArray().forEach(rowEl => {
const row = $(rowEl);
const cell = row.find('td').eq(cellId);
const cellMarkerInfo = [];
cell.find('.marker-data-node')
.toArray()
.forEach(cellEl => {
const cellRef = $(cellEl);
const nodeName = cellRef.text().replace(/\n/g, '').trim();
const nodeInfo = lookupTable.node_info[nodeName];
if (!nodeInfo || !nodeInfo.marker_data) return;
const markerData = [];
for (const markerRef of nodeInfo.marker_data) {
// create a deep copy so we arent editing the original
const markerCopy = JSON.parse(JSON.stringify(markerRef));
markerCopy.use_case = 'node';
markerCopy.part_number = nodeInfo.part_number;
markerCopy.description = lookupTable.part_info[nodeInfo.part_number].description;
markerCopy.node_name = nodeInfo.node_name;
markerCopy.node = nodeInfo.node_name;
markerCopy.net_name = nodeInfo.net_name;
markerCopy.pin_name = nodeInfo.pin_name;
markerData.push(markerCopy);
}
cellMarkerInfo.push(markerData);
});
cell.find('.marker-data-refdes')
.toArray()
.forEach(cellEl => {
const cellRef = $(cellEl);
const refdes = cellRef.text().replace(/\n/g, '').trim();
const refdesInfo = lookupTable.refdes_info[refdes];
if (!refdesInfo || !refdesInfo.marker_data) return;
const markerData = [];
for (const markerRef of refdesInfo.marker_data) {
// create a deep copy so we arent editing the original
const markerCopy = JSON.parse(JSON.stringify(markerRef));
markerCopy.use_case = 'refdes';
markerCopy.part_number = refdesInfo.part_number;
markerCopy.description = lookupTable.part_info[refdesInfo.part_number].description;
markerCopy.refdes = refdesInfo.refdes;
markerData.push(markerCopy);
}
cellMarkerInfo.push(markerData);
});
markers.push({ 'reportColumn': columnName, 'reportName': reportName, 'markerData': cellMarkerInfo });
});
return markers;
}
function setBodyKonvaNetTrace(tableVariableName, netName) {
$('body').html('');
var container = $('
');
container.css('padding', '10px');
var crossProbeContainer = $('');
crossProbeContainer.addClass('noprint');
crossProbeContainer.text('Ctrl+Scroll to zoom in/out | Ctrl+Click and drag to pan | ');
var netTraceSearchBar = $('');
netTraceSearchBar.on('keyup', (e) => {
const searchText = $(e.target).val();
var searchGroup = stage.findOne('.search-group');
var parentLayer = searchGroup.getParent();
// delete all the old search nodes
searchGroup.destroy();
// create a new search group
searchGroup = new Konva.Group({ name: 'search-group' });
// add the new search group to the search drawing layer
parentLayer.add(searchGroup);
if (!searchText) return;
for (const textObject of stage.findOne('.drawing-group').find('Text')) { // TODO cache this query for optimization
const textToSearch = textObject.text();
const match = equalsContainsMatches(textToSearch, searchText);
if (match) {
const searchLabel = new Konva.Label({
name: 'search-label',
opacity: 1,
x: textObject.getAbsolutePosition(stage).x - 1,
y: textObject.getAbsolutePosition(stage).y - 1,
});
searchLabel.add(new Konva.Tag({
fill: 'yellow',
cornerRadius: 1,
}));
searchLabel.add(new Konva.Text({
text: textToSearch,
fontSize: textObject.getAttr('fontSize'),
fontStyle: textObject.getAttr('fontStyle'),
padding: 1,
}));
searchGroup.add(searchLabel);
}
}
});
crossProbeContainer.append(netTraceSearchBar);
var ahdlButton = $('');
var captureButton = $('');
var pcbButton = $('');
ahdlButton.click((e) => {
var markers = netTraceMarker(dataTable, netName);
var text = generateMarkerText(markers);
downloadTextToFile(text, reportName + '_AHDL_NetTrace.mkr');
});
captureButton.click((e) => {
var markers = netTraceMarker(dataTable, netName);
var text = makeTclReadableMarker(markers);
downloadTextToFile(text, reportName + '_Capture_NetTrace.mkr');
});
pcbButton.click((e) => {
var text = currentTraceNodes.join('\n');
downloadTextToFile(text, reportName + '_PCB_NetTrace.txt');
});
crossProbeContainer.append(ahdlButton);
crossProbeContainer.append(captureButton);
crossProbeContainer.append(pcbButton);
container.append(crossProbeContainer);
var rightButtonContainer = $('');
rightButtonContainer.addClass('noprint');
rightButtonContainer.css('float', 'right');
var refreshButton = $('