hledger/hledger-web/static/hledger.js
2022-08-27 12:12:14 +01:00

234 lines
7.5 KiB
JavaScript

/* hledger web ui javascript */
//----------------------------------------------------------------------
// STARTUP
$(document).ready(function() {
// add form helpers XXX move to addForm ?
// date picker
// http://bootstrap-datepicker.readthedocs.io/en/latest/options.html
var dateEl = $('#dateWrap').datepicker({
showOnFocus: false,
autoclose: true,
format: 'yyyy-mm-dd',
todayHighlight: true,
weekStart: 1 // Monday
});;
// focus and pre-fill the add form whenever it is shown
$('#addmodal')
.on('shown.bs.modal', function() {
addformFocus();
})
.on('hidden.bs.modal', function() {
// close the date picker if open
dateEl.datepicker('hide');
});
// ensure that the keypress listener on the final amount input is always active
$('#addform')
.on('focus', '.amount-input:last', function() {
addformLastAmountBindKey();
});
// keyboard shortcuts
// 'body' seems to hold focus better than document in FF
$('body').bind('keydown', 'h', function(){ $('#helpmodal').modal('toggle'); return false; });
$('body').bind('keydown', 'shift+/', function(){ $('#helpmodal').modal('toggle'); return false; });
$('body').bind('keydown', 'j', function(){ location.href = document.hledgerWebBaseurl+'/journal'; return false; });
$('body').bind('keydown', 's', function(){ sidebarToggle(); return false; });
$('body').bind('keydown', 'e', function(){ emptyAccountsToggle(); return false; });
$('body').bind('keydown', 'a', function(){ addformShow(); return false; });
$('body').bind('keydown', 'n', function(){ addformShow(); return false; });
$('body').bind('keydown', 'f', function(){ $('#searchform input').focus(); return false; });
// highlight the entry from the url hash
if (window.location.hash && $(window.location.hash)[0]) {
$(window.location.hash).addClass('highlighted');
}
$(window).on('hashchange', function() {
$('.highlighted').removeClass('highlighted');
$(window.location.hash).addClass('highlighted');
});
$('[data-toggle="offcanvas"]').click(function () {
$('.row-offcanvas').toggleClass('active');
});
});
//----------------------------------------------------------------------
// REGISTER CHART
//eslint-disable-next-line no-unused-vars
function registerChart($container, series) {
// https://github.com/flot/flot/blob/master/API.md
return $container.plot(
series,
{ /* general chart options */
xaxis: {
mode: "time",
timeformat: "%Y/%m/%d",
},
selection: {
mode: "x"
},
legend: {
position: 'sw'
},
grid: {
markings: function () {
var now = Date.now();
return [
{
xaxis: { to: now }, // past
yaxis: { to: 0 }, // <0
color: '#ffdddd',
},
{
xaxis: { from: now }, // future
yaxis: { from: 0 }, // >0
color: '#e0e0e0',
},
{
xaxis: { from: now }, // future
yaxis: { to: 0 }, // <0
color: '#e8c8c8',
},
{
yaxis: { from: 0, to: 0 }, // =0
color: '#bb0000',
lineWidth:1
},
];
},
hoverable: true,
autoHighlight: true,
clickable: true,
},
/* https://github.com/krzysu/flot.tooltip */
tooltip: true,
tooltipOpts: {
xDateFormat: "%Y/%m/%d",
content:
function(label, x, y, flotitem) {
var data = flotitem.series.data[flotitem.dataIndex];
return data[3]+" balance on %x after "+data[2]+" posted by transaction:<pre>"+data[4]+"</pre>";
},
onHover: function(flotitem, $tooltipel) {
$tooltipel.css('border-color',flotitem.series.color);
},
},
}
).data("plot");
}
function registerChartClick(ev, pos, item) {
if (!item) {
return;
}
var targetselector = '#' + item.series.data[item.dataIndex][5];
var $target = $(targetselector);
if ($target.length) {
window.location.hash = targetselector;
$('html, body').animate({
scrollTop: $target.offset().top
}, 1000);
}
}
//----------------------------------------------------------------------
// ADD FORM
function addformShow(showmsg) {
showmsg = typeof showmsg !== 'undefined' ? showmsg : false;
addformReset(showmsg);
$('#addmodal').modal('show');
}
// Make sure the add form is empty and clean and has the default number of rows.
function addformReset(showmsg) {
showmsg = typeof showmsg !== 'undefined' ? showmsg : false;
if ($('form#addform').length > 0) {
if (!showmsg) $('div#message').html('');
$('#addform .account-group.added-row').remove();
addformLastAmountBindKey();
$('#addform')[0].reset();
// reset typehead state (though not fetched completions)
$('.typeahead').typeahead('val', '');
$('.tt-dropdown-menu').hide();
}
}
// Set the add-new-row-on-keypress handler on the add form's current last amount field, only.
// (NB: removes all other keypress handlers from all amount fields).
function addformLastAmountBindKey() {
$('.amount-input').off('keypress');
$('.amount-input:last').keypress(addformAddPosting);
}
// Pre-fill today's date and focus the description field in the add form.
function addformFocus() {
$('#addform input[name=date]').val(isoDate());
focus($('#addform input[name=description]'));
}
function isoDate() {
return new Date().toLocaleDateString("sv"); // https://stackoverflow.com/a/58633651/84401
}
// Focus a jquery-wrapped element, working around http://stackoverflow.com/a/7046837.
function focus($el) {
setTimeout(function (){
$el.focus();
}, 0);
}
// Insert another posting row in the add form.
function addformAddPosting() {
if (!$('#addform').is(':visible')) {
return;
}
// Clone the old last row to make a new last row
$('#addform .account-postings').append( $('#addform .account-group:last').clone().addClass('added-row') );
// renumber and clear the new last account and amount fields
var n = $('#addform .account-group').length;
$('.account-input:last').prop('placeholder', 'Account '+n).val('');
$('.amount-input:last').prop('placeholder','Amount '+n).val(''); // XXX Enable typehead on dynamically created inputs
// and move the keypress handler to the new last amount field
addformLastAmountBindKey();
}
// Remove the add form's last posting row, if empty, keeping at least two.
function addformDeletePosting() {
if ($('#addform .account-group').length <= 2) {
return;
}
// remember if the last row's field or button had focus
var focuslost =
$('.account-input:last').is(':focus')
|| $('.amount-input:last').is(':focus');
// delete last row
$('#addform .account-group:last').remove();
if (focuslost) {
focus($('.account-input:last'));
}
// move the keypress handler to the new last amount field
addformLastAmountBindKey();
}
//----------------------------------------------------------------------
// SIDEBAR
function sidebarToggle() {
$('#sidebar-menu').toggleClass('col-md-4 col-sm-4 col-any-0');
$('#main-content').toggleClass('col-md-8 col-sm-8 col-md-12 col-sm-12');
$('#spacer').toggleClass('col-md-4 col-sm-4 col-any-0');
$.cookie('showsidebar', $('#sidebar-menu').hasClass('col-any-0') ? '0' : '1');
}
function emptyAccountsToggle() {
$('.acct.empty').parent().toggleClass('hide');
$.cookie('hideemptyaccts', $.cookie('hideemptyaccts') === '1' ? '0' : '1')
}