Skip to content

Commit c71cebc

Browse files
committed
Add custom js css and header/footer support
Fixes #125 Fixes #72
1 parent 28352de commit c71cebc

File tree

5 files changed

+64
-3
lines changed

5 files changed

+64
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ test
66
releases
77
demo
88
config.ini
9+
InteractiveHtmlBom/web/user*

InteractiveHtmlBom/core/ibom.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,11 @@ def get_compressed_pcbdata(pcbdata):
224224
def generate_file(pcb_file_dir, pcb_file_name, pcbdata, config):
225225
def get_file_content(file_name):
226226
path = os.path.join(os.path.dirname(__file__), "..", "web", file_name)
227+
if not os.path.exists(path):
228+
return ""
227229
with io.open(path, 'r', encoding='utf-8') as f:
228230
return f.read()
229231

230-
log.info("Dumping pcb json data")
231232

232233
if os.path.isabs(config.bom_dest_dir):
233234
bom_file_dir = config.bom_dest_dir
@@ -239,18 +240,26 @@ def get_file_content(file_name):
239240
bom_file_dir = os.path.dirname(bom_file_name)
240241
if not os.path.isdir(bom_file_dir):
241242
os.makedirs(bom_file_dir)
243+
log.info("Compressing pcb data")
244+
compressed_pcbdata = get_compressed_pcbdata(pcbdata)
245+
log.info("Dumping pcb data")
242246
config_js = "var config = " + config.get_html_config()
243247
html = get_file_content("ibom.html")
244248
html = html.replace('///CSS///', get_file_content('ibom.css'))
249+
html = html.replace('///USERCSS///', get_file_content('user.css'))
245250
html = html.replace('///SPLITJS///', get_file_content('split.js'))
246251
html = html.replace('///LZ-STRING///', get_file_content('lz-string.js'))
247252
html = html.replace('///POINTER_EVENTS_POLYFILL///',
248253
get_file_content('pep.js'))
249254
html = html.replace('///CONFIG///', config_js)
250-
html = html.replace('///PCBDATA///', get_compressed_pcbdata(pcbdata))
255+
html = html.replace('///PCBDATA///', compressed_pcbdata)
251256
html = html.replace('///UTILJS///', get_file_content('util.js'))
252257
html = html.replace('///RENDERJS///', get_file_content('render.js'))
253258
html = html.replace('///IBOMJS///', get_file_content('ibom.js'))
259+
html = html.replace('///USERJS///', get_file_content('user.js'))
260+
html = html.replace('///USERHEADER///', get_file_content('userheader.html'))
261+
html = html.replace('///USERFOOTER///', get_file_content('userfooter.html'))
262+
254263
with io.open(bom_file_name, 'wt', encoding='utf-8') as bom:
255264
bom.write(html)
256265
log.info("Created file %s", bom_file_name)

InteractiveHtmlBom/web/ibom.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<title>Interactive BOM for KiCAD</title>
88
<style type="text/css">
99
///CSS///
10+
///USERCSS///
1011
</style>
1112
<script type="text/javascript" >
1213
///////////////////////////////////////////////
@@ -41,10 +42,14 @@
4142
///IBOMJS///
4243
///////////////////////////////////////////////
4344

45+
///////////////////////////////////////////////
46+
///USERJS///
47+
///////////////////////////////////////////////
4448
</script>
4549
</head>
4650

4751
<body>
52+
///USERHEADER///
4853
<div id="topmostdiv" class="topmostdiv">
4954
<div id="top">
5055
<div style="float: right; height: 100%;">
@@ -292,6 +297,7 @@
292297
</div>
293298
</div>
294299
</div>
300+
///USERFOOTER///
295301
</body>
296302

297303
</html>

InteractiveHtmlBom/web/ibom.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ function createCheckboxChangeHandler(checkbox, references) {
153153
return function(evt) {
154154
refsSet = getStoredCheckboxRefs(checkbox);
155155
var darkenWhenChecked = settings.darkenWhenChecked == checkbox;
156+
eventArgs = {
157+
checkbox: checkbox,
158+
refs: references,
159+
}
156160
if (this.checked) {
157161
// checkbox ticked
158162
for (var ref of references) {
@@ -161,6 +165,7 @@ function createCheckboxChangeHandler(checkbox, references) {
161165
if (darkenWhenChecked) {
162166
evt.target.parentElement.parentElement.classList.add("checked");
163167
}
168+
eventArgs.state = 'checked';
164169
} else {
165170
// checkbox unticked
166171
for (var ref of references) {
@@ -169,10 +174,12 @@ function createCheckboxChangeHandler(checkbox, references) {
169174
if (darkenWhenChecked) {
170175
evt.target.parentElement.parentElement.classList.remove("checked");
171176
}
177+
eventArgs.state = 'unchecked';
172178
}
173179
settings.checkboxStoredRefs[checkbox] = [...refsSet].join(",");
174180
writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
175181
updateCheckboxStats(checkbox);
182+
EventHandler.emitEvent(IBOM_EVENT_TYPES.CHECKBOX_CHANGE_EVENT, eventArgs);
176183
}
177184
}
178185

@@ -198,6 +205,13 @@ function createRowHighlightHandler(rowid, refs, net) {
198205
highlightedModules = refs ? refs.map(r => r[1]) : [];
199206
highlightedNet = net;
200207
drawHighlights();
208+
EventHandler.emitEvent(
209+
IBOM_EVENT_TYPES.HIGHLIGHT_EVENT,
210+
{
211+
rowid: rowid,
212+
refs: refs,
213+
net: net
214+
});
201215
}
202216
}
203217

@@ -871,7 +885,7 @@ function populateDarkenWhenCheckedOptions() {
871885

872886
container.innerHTML = '';
873887
container.parentElement.style.display = "inline-block";
874-
888+
875889
function createOption(name, displayName) {
876890
var id = "darkenWhenChecked-" + name;
877891

InteractiveHtmlBom/web/util.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,3 +518,34 @@ function initDefaults() {
518518
document.getElementById("boardRotation").value = settings.boardRotation / 5;
519519
document.getElementById("rotationDegree").textContent = settings.boardRotation;
520520
}
521+
522+
// Helper classes for user js callbacks.
523+
524+
const IBOM_EVENT_TYPES = {
525+
ALL: "all",
526+
HIGHLIGHT_EVENT: "highlightEvent",
527+
CHECKBOX_CHANGE_EVENT: "checkboxChangeEvent",
528+
}
529+
530+
const EventHandler = {
531+
callbacks: {},
532+
init: function() {
533+
for (eventType of Object.values(IBOM_EVENT_TYPES))
534+
this.callbacks[eventType] = [];
535+
},
536+
registerCallback: function(eventType, callback) {
537+
this.callbacks[eventType].push(callback);
538+
},
539+
emitEvent: function(eventType, eventArgs) {
540+
event = {
541+
eventType: eventType,
542+
args: eventArgs,
543+
}
544+
var callback;
545+
for(callback of this.callbacks[eventType])
546+
callback(event);
547+
for(callback of this.callbacks[IBOM_EVENT_TYPES.ALL])
548+
callback(event);
549+
}
550+
}
551+
EventHandler.init();

0 commit comments

Comments
 (0)