Skip to content

Commit 43587ca

Browse files
committed
Add resizable column border
Fixes #255
1 parent de62198 commit 43587ca

File tree

5 files changed

+125
-25
lines changed

5 files changed

+125
-25
lines changed

InteractiveHtmlBom/core/ibom.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def __init__(self, cli=False):
2626
ch = logging.StreamHandler(sys.stdout)
2727
ch.setLevel(logging.INFO)
2828
formatter = logging.Formatter(
29-
"%(asctime)-15s %(levelname)s %(message)s")
29+
"%(asctime)-15s %(levelname)s %(message)s")
3030
ch.setFormatter(formatter)
3131
self.logger.addHandler(ch)
3232

@@ -237,7 +237,7 @@ def get_file_content(file_name):
237237
else:
238238
bom_file_dir = os.path.join(pcb_file_dir, config.bom_dest_dir)
239239
bom_file_name = process_substitutions(
240-
config.bom_name_format, pcb_file_name, pcbdata['metadata'])
240+
config.bom_name_format, pcb_file_name, pcbdata['metadata'])
241241
bom_file_name = os.path.join(bom_file_dir, bom_file_name)
242242
bom_file_dir = os.path.dirname(bom_file_name)
243243
if not os.path.isdir(bom_file_dir):
@@ -257,7 +257,7 @@ def get_file_content(file_name):
257257
html = html.replace('///CONFIG///', config_js)
258258
html = html.replace('///UTILJS///', get_file_content('util.js'))
259259
html = html.replace('///RENDERJS///', get_file_content('render.js'))
260-
html = html.replace('///TABLEDRAG///', get_file_content('table-drag.js'))
260+
html = html.replace('///TABLEUTILJS///', get_file_content('table-util.js'))
261261
html = html.replace('///IBOMJS///', get_file_content('ibom.js'))
262262
html = html.replace('///USERJS///', get_file_content('user.js'))
263263
html = html.replace('///USERHEADER///',
@@ -311,7 +311,7 @@ def save_config(dialog_panel):
311311
try:
312312
config.netlist_initial_directory = os.path.dirname(parser.file_name)
313313
extra_data_file = parser.latest_extra_data(
314-
extra_dirs=[config.bom_dest_dir])
314+
extra_dirs=[config.bom_dest_dir])
315315
if extra_data_file is not None:
316316
dlg.set_extra_data_path(extra_data_file)
317317
config.transfer_to_dialog(dlg.panel)

InteractiveHtmlBom/web/ibom.css

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,3 +767,27 @@ a {
767767
.dark .placeholder {
768768
filter: invert(1);
769769
}
770+
771+
.column-spacer {
772+
top: 0;
773+
left: 0;
774+
width: calc(100% - 4px);
775+
position: absolute;
776+
cursor: pointer;
777+
user-select: none;
778+
height: 100%;
779+
}
780+
781+
.column-width-handle {
782+
top: 0;
783+
right: 0;
784+
width: 4px;
785+
position: absolute;
786+
cursor: col-resize;
787+
user-select: none;
788+
height: 100%;
789+
}
790+
791+
.column-width-handle:hover {
792+
background-color: #4f99bd;
793+
}

InteractiveHtmlBom/web/ibom.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
///////////////////////////////////////////////
4040

4141
///////////////////////////////////////////////
42-
///TABLEDRAG///
42+
///TABLEUTILJS///
4343
///////////////////////////////////////////////
4444

4545
///////////////////////////////////////////////

InteractiveHtmlBom/web/ibom.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ function createCheckboxChangeHandler(checkbox, references, row) {
196196
}
197197
if (markWhenChecked) {
198198
row.classList.add("checked");
199-
for(var ref of references) {
199+
for (var ref of references) {
200200
markedFootprints.add(ref[1]);
201201
}
202202
drawHighlights();
@@ -209,7 +209,7 @@ function createCheckboxChangeHandler(checkbox, references, row) {
209209
}
210210
if (markWhenChecked) {
211211
row.classList.remove("checked");
212-
for(var ref of references) {
212+
for (var ref of references) {
213213
markedFootprints.delete(ref[1]);
214214
}
215215
drawHighlights();
@@ -354,20 +354,22 @@ function createColumnHeader(name, cls, comparator, is_checkbox = false) {
354354
th.setAttribute("col_name", "bom-checkbox");
355355
else
356356
th.setAttribute("col_name", name);
357-
th.style.cursor = "pointer";
358357
var span = document.createElement("SPAN");
359358
span.classList.add("sortmark");
360359
span.classList.add("none");
361360
th.appendChild(span);
362-
th.onclick = function() {
363-
if (currentSortColumn && this !== currentSortColumn) {
361+
var spacer = document.createElement("div");
362+
spacer.className = "column-spacer";
363+
th.appendChild(spacer);
364+
spacer.onclick = function() {
365+
if (currentSortColumn && th !== currentSortColumn) {
364366
// Currently sorted by another column
365367
currentSortColumn.childNodes[1].classList.remove(currentSortOrder);
366368
currentSortColumn.childNodes[1].classList.add("none");
367369
currentSortColumn = null;
368370
currentSortOrder = null;
369371
}
370-
if (currentSortColumn && this === currentSortColumn) {
372+
if (currentSortColumn && th === currentSortColumn) {
371373
// Already sorted by this column
372374
if (currentSortOrder == "asc") {
373375
// Sort by this column, descending order
@@ -388,13 +390,17 @@ function createColumnHeader(name, cls, comparator, is_checkbox = false) {
388390
} else {
389391
// Sort by this column, ascending order
390392
bomSortFunction = comparator;
391-
currentSortColumn = this;
393+
currentSortColumn = th;
392394
currentSortColumn.childNodes[1].classList.remove("none");
393395
currentSortColumn.childNodes[1].classList.add("asc");
394396
currentSortOrder = "asc";
395397
}
396398
populateBomBody();
397399
}
400+
if (is_checkbox) {
401+
spacer.onclick = fancyDblClickHandler(
402+
spacer, spacer.onclick, checkboxSetUnsetAllHandler(name));
403+
}
398404
return th;
399405
}
400406

@@ -489,8 +495,6 @@ function populateBomHeader(placeHolderColumn = null, placeHolderElements = null)
489495
for (var checkbox of settings.checkboxes) {
490496
th = createColumnHeader(
491497
checkbox, "bom-checkbox", checkboxCompareClosure(checkbox), true);
492-
th.onclick = fancyDblClickHandler(
493-
th, th.onclick.bind(th), checkboxSetUnsetAllHandler(checkbox));
494498
tr.appendChild(th);
495499
}
496500
}
@@ -739,6 +743,7 @@ function populateBomTable() {
739743
populateBomHeader();
740744
populateBomBody();
741745
setBomHandlers();
746+
resizableGrid(bomhead);
742747
}
743748

744749
function footprintsClicked(footprintIndexes) {
@@ -1014,7 +1019,7 @@ function setMarkWhenChecked(value) {
10141019
writeStorage("markWhenChecked", value);
10151020
settings.markWhenChecked = value;
10161021
markedFootprints.clear();
1017-
for(var ref of (value ? getStoredCheckboxRefs(value) : [])) {
1022+
for (var ref of (value ? getStoredCheckboxRefs(value) : [])) {
10181023
markedFootprints.add(ref);
10191024
}
10201025
populateBomTable();

InteractiveHtmlBom/web/table-drag.js renamed to InteractiveHtmlBom/web/table-util.js

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ function setBomHandlers() {
142142
}
143143

144144
const mouseDownHandler = function(e) {
145-
// The sortmark shouldn't be draggable
146-
if (e.target.classList.contains("sortmark"))
147-
return;
145+
var target = e.target;
146+
if (target.tagName.toLowerCase() != "td")
147+
target = target.parentElement;
148148

149149
// Used to check if a dragging has ever happened
150150
wasDragged = false;
@@ -161,10 +161,10 @@ function setBomHandlers() {
161161

162162
// Get all compound headers for the current column
163163
var compoundHeaders;
164-
if (e.target.classList.contains("bom-checkbox")) {
164+
if (target.classList.contains("bom-checkbox")) {
165165
compoundHeaders = Array.from(bh.querySelectorAll("th.bom-checkbox"));
166166
} else {
167-
compoundHeaders = [e.target];
167+
compoundHeaders = [target];
168168
}
169169

170170
// Create new table which will display the column
@@ -223,7 +223,7 @@ function setBomHandlers() {
223223
yOffset = e.screenY - compoundHeaders[0].offsetTop;
224224

225225
// Get name for the column in settings.columnOrder
226-
dragName = getColumnOrderName(e.target);
226+
dragName = getColumnOrderName(target);
227227

228228
// Change text and class for placeholder elements
229229
placeHolderElements = placeHolderElements.map(function(e) {
@@ -277,10 +277,8 @@ function getBoundingClientRectFromMultiple(elements) {
277277

278278
function cloneElementWithDimensions(elem) {
279279
var newElem = elem.cloneNode(true);
280-
newElem.style.height = window.getComputedStyle(elem)
281-
.height;
282-
newElem.style.width = window.getComputedStyle(elem)
283-
.width;
280+
newElem.style.height = window.getComputedStyle(elem).height;
281+
newElem.style.width = window.getComputedStyle(elem).width;
284282
return newElem;
285283
}
286284

@@ -297,3 +295,76 @@ function getColumnOrderName(elem) {
297295
else
298296
return cname;
299297
}
298+
299+
function resizableGrid(tablehead) {
300+
var cols = tablehead.firstElementChild.children;
301+
var rowWidth = tablehead.offsetWidth;
302+
303+
for (var i = 1; i < cols.length; i++) {
304+
if (cols[i].classList.contains("bom-checkbox"))
305+
continue;
306+
cols[i].style.width = ((cols[i].clientWidth - paddingDiff(cols[i])) * 100 / rowWidth) + '%';
307+
}
308+
309+
for (var i = 1; i < cols.length - 1; i++) {
310+
var div = document.createElement('div');
311+
div.className = "column-width-handle";
312+
cols[i].appendChild(div);
313+
setListeners(div);
314+
}
315+
316+
function setListeners(div) {
317+
var startX, curCol, nxtCol, curColWidth, nxtColWidth, rowWidth;
318+
319+
div.addEventListener('mousedown', function(e) {
320+
e.preventDefault();
321+
e.stopPropagation();
322+
323+
curCol = e.target.parentElement;
324+
nxtCol = curCol.nextElementSibling;
325+
startX = e.pageX;
326+
327+
var padding = paddingDiff(curCol);
328+
329+
rowWidth = curCol.parentElement.offsetWidth;
330+
curColWidth = curCol.clientWidth - padding;
331+
nxtColWidth = nxtCol.clientWidth - padding;
332+
});
333+
334+
document.addEventListener('mousemove', function(e) {
335+
if (startX) {
336+
var diffX = e.pageX - startX;
337+
diffX = -Math.min(-diffX, curColWidth - 20);
338+
diffX = Math.min(diffX, nxtColWidth - 20);
339+
340+
curCol.style.width = ((curColWidth + diffX) * 100 / rowWidth) + '%';
341+
nxtCol.style.width = ((nxtColWidth - diffX) * 100 / rowWidth) + '%';
342+
console.log(`${curColWidth + nxtColWidth} ${(curColWidth + diffX) * 100 / rowWidth + (nxtColWidth - diffX) * 100 / rowWidth}`);
343+
}
344+
});
345+
346+
document.addEventListener('mouseup', function(e) {
347+
curCol = undefined;
348+
nxtCol = undefined;
349+
startX = undefined;
350+
nxtColWidth = undefined;
351+
curColWidth = undefined
352+
});
353+
}
354+
355+
function paddingDiff(col) {
356+
357+
if (getStyleVal(col, 'box-sizing') == 'border-box') {
358+
return 0;
359+
}
360+
361+
var padLeft = getStyleVal(col, 'padding-left');
362+
var padRight = getStyleVal(col, 'padding-right');
363+
return (parseInt(padLeft) + parseInt(padRight));
364+
365+
}
366+
367+
function getStyleVal(elm, css) {
368+
return (window.getComputedStyle(elm, null).getPropertyValue(css))
369+
}
370+
}

0 commit comments

Comments
 (0)