Skip to content

Instantly share code, notes, and snippets.

@brianvanderburg2
Created October 18, 2024 03:12
Show Gist options
  • Save brianvanderburg2/a23384b73be410685aa4575d7554b78f to your computer and use it in GitHub Desktop.
Save brianvanderburg2/a23384b73be410685aa4575d7554b78f to your computer and use it in GitHub Desktop.
Trilium calculator note widget
/* Create a code note, type JS Frontend, copy this entire text into it.
Add the following owned attributes to the widget note:
#widget #label:globalDisable="promoted,alias=Disable,single,boolean" #label:position="promoted,alias=Location (top/bottom),single,text" #globalDisable=false #position=top
To create a calculator note, create another code note type JS Frontend with the #calculator attribute set
Example calculator code note content:
module.exports = {
fields: function() {
return [
{ name: "r", desc: "radius" },
{ name: "d", desc: "diameter" },
{ name: "c", desc: "circumference" }
]
},
calculate: function(values) {
return [
{ desc: "radius", value: values["r"] },
{ desc: "diameter", value: values["d"] },
{ desc: "circumference", value: values["c"] },
]
}
}
*/
var TPL=`
<div class="calculatorContainer">
<div class="calculatorBody"></div>
</div>
`;
var STYLES=`
.calculatorContainer { display: block; margin-left: auto; margin-right: auto; contain: none; }
.calculatorButtons { text-align: center; display: block; margin-left: auto; margin-right: auto; }
.calculatorInput td:first-child { text-align: right; }
.calculatorOutput td:first-child { text-align: right; }
.calculatorOutput td:first-child:after { content: " : " }
`;
var position = api.startNote.getLabelValue("position") ?? "top";
class CalculatorWidget extends api.NoteContextAwareWidget {
get position() {
return position === "bottom" ? 100 : 50;
}
static get parentWidget() {
return "note-detail-pane";
}
constructor() {
super();
}
isEnabled() {
if(!super.isEnabled()) {
return false;
}
if(api.startNote.getLabelValue("globalDisable") === "true") {
return false;
}
if(this.note == null) {
return false;
}
return this.note.hasLabel("calculator");
}
doRender() {
this.$widget = $(TPL);
this.$body = this.$widget.find(".calculatorBody");
this.cssBlock(STYLES);
return this.$widget;
}
async refreshWithNote() {
await this.buildCalculator(this.note);
}
async buildCalculator(note) {
if(!note) { return; }
if(await this.note.hasLabel("calculator")) {
var exports = await note.executeScript();
var fields = exports.fields();
var calculate = exports.calculate;
// input section
var $input = $('<form action="javascript:void(0);">');
var $table = $('<table class="calculatorInput">').appendTo($input);
fields.forEach(field => {
var $row = $('<tr>').appendTo($table);
$row.append($('<td>').text(field.desc));
$row.append($('<td><input type="text" name="' + field.name + '"></td>'));
});
// buttons
var $buttons = $('<div class="calculatorButtons">').appendTo($input);
$buttons.append('<input type="submit" value="Calculate">');
$buttons.append('<input type="reset" value="Clear">');
// output section
var $output = $('<div></div>');
// body
this.$body.empty();
this.$body.append($input);
this.$body.append($output);
// events
$input.on("submit", event => {
$output.empty();
var values = [];
fields.forEach(field => {
values[field.name] = $input.find('[name="' + field.name + '"]').val()
});
var results = calculate(values);
var $outTable = $('<table class="calculatorOutput">')
results.forEach(result => {
var $outRow = $('<tr>').appendTo($outTable);
$outRow.append($('<td>').text(result.desc));
$outRow.append($('<td>').text(result.value));
});
$output.append($outTable);
event.preventDefault();
});
}
return;
}
};
module.exports = CalculatorWidget;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment