/* hledger web ui javascript */ //---------------------------------------------------------------------- // STARTUP $(document).ready(function() { // show add form if ?add=1 if ($.url.param('add')) { addformShow(); } // sidebar account hover handlers $('#sidebar td a').mouseenter(function(){ $(this).parent().addClass('mouseover'); }); $('#sidebar td').mouseleave(function(){ $(this).removeClass('mouseover'); }); // keyboard shortcuts // 'body' seems to hold focus better than document in FF $('body').bind('keydown', 'shift+/', function(){ $('#helpmodal').modal('toggle'); return false; }); $('body').bind('keydown', 'h', function(){ $('#helpmodal').modal('toggle'); return false; }); $('body').bind('keydown', 'j', function(){ location.href = '/journal'; return false; }); $('body').bind('keydown', 's', function(){ sidebarToggle(); return false; }); $('body').bind('keydown', 'a', function(){ addformShow(); return false; }); $('body').bind('keydown', 'n', function(){ addformShow(); return false; }); $('body').bind('keydown', '/', function(){ $('#searchform input').focus(); return false; }); $('body, #addform input').bind('keydown', 'ctrl+shift+=', addformAddPosting); $('body, #addform input').bind('keydown', 'ctrl+=', addformAddPosting); $('body, #addform input').bind('keydown', 'ctrl+-', addformDeletePosting); $('#addform tr.posting:last > td:first input').bind('keydown', 'tab', addformAddPostingWithTab); }); //---------------------------------------------------------------------- // REGISTER CHART function registerChart($container, series) { // https://github.com/flot/flot/blob/master/API.md return $container.plot( series, { /* general chart options */ series: { points: { show: true, }, lines: { show: true, steps: true, }, bars: { // show: true, // barWidth: 1000 * 60 * 60, // ms }, }, yaxis: { /* mode: "time", */ /* timeformat: "%y/%m/%d", */ /* ticks: 6, */ }, xaxis: { mode: "time", timeformat: "%Y/%m/%d" /* ticks: 6, */ }, grid: { // clickable: true, // hoverable: true, // autoHighlight: true, markings: function (axes) { // console.log(axes); // var markings = []; // for (var x = Math.floor(axes.xaxis.min); x < axes.xaxis.max; x += 2) // markings.push({ xaxis: { from: x, to: x + 1 } }); // midx = Math.floor(axes.xaxis.min + (axes.xaxis.max - axes.xaxis.min) / 2); var now = Date.now(); var markings = [ { xaxis: { from: now, to: now }, color: '#888', lineWidth:1 }, { yaxis: { from: 0, to: 0 }, color: '#bb0000', lineWidth:1 }, ]; // console.log(markings); return markings; } }, } ).data("plot"); } //---------------------------------------------------------------------- // ADD FORM function addformShow() { addformReset(); $('#addmodal') .on('shown.bs.modal', function (e) { addformFocus(); }) .modal('show'); } // Make sure the add form is empty and clean for display. function addformReset() { if ($('form#addform').length > 0) { $('form#addform')[0].reset(); $('input#date').val('today'); // reset typehead state (though not fetched completions) $('.typeahead').typeahead('val', ''); $('.tt-dropdown-menu').hide(); } } // Focus the first add form field. function addformFocus() { focus($('#addform input#date')); } // 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() { // do nothing if it's not currently visible if (!$('#addform').is(':visible')) return; // save a copy of last row var lastrow = $('#addform tr.posting:last').clone(); // replace the submit button with an amount field, clear and renumber it, add the keybindings $('#addform tr.posting:last > td:last') .html( $('#addform tr.posting:first > td:last').html() ); var num = $('#addform tr.posting').length; $('#addform tr.posting:last > td:last input:last') // input:last here and elsewhere is to avoid autocomplete's extra input .val('') .prop('id','amount'+num) .prop('name','amount'+num) .prop('placeholder','Amount '+num) .bind('keydown', 'ctrl+shift+=', addformAddPosting) .bind('keydown', 'ctrl+=', addformAddPosting) .bind('keydown', 'ctrl+-', addformDeletePosting); // set up the new last row's account field. // First typehead, it's hard to enable on new DOM elements var $acctinput = lastrow.find('.account-input:last'); // XXX nothing works // $acctinput.typeahead('destroy'); //,'NoCached'); // lastrow.on("DOMNodeInserted", function () { // //$(this).find(".typeahead").typeahead(); // console.log('DOMNodeInserted'); // // infinite loop // console.log($(this).find('.typeahead')); // //enableTypeahead($(this).find('.typeahead'), accountsSuggester); // }); // setTimeout(function (){ // $('#addform tr.posting:last input.account-input').typeahead('destroy'); // enableTypeahead($('#addform tr.posting:last input.account-input:last'), accountsSuggester); // }, 1000); // insert the new last row $('#addform > table > tbody').append(lastrow); // clear and renumber the field, add keybindings $acctinput .val('') .prop('id','account'+(num+1)) .prop('name','account'+(num+1)) .prop('placeholder','Account '+(num+1)); //lastrow.find('input') // not :last this time $acctinput .bind('keydown', 'ctrl+shift+=', addformAddPosting) .bind('keydown', 'ctrl+=', addformAddPosting) .bind('keydown', 'ctrl+-', addformDeletePosting) .bind('keydown', 'tab', addformAddPostingWithTab); } // Insert another posting row by tabbing within the last field, also advancing the focus. function addformAddPostingWithTab(ev) { // do nothing if called from a non-last row (don't know how to remove keybindings) if ($(ev.target).is('#addform input.account-input:last')) { addformAddPosting(); focus($('#addform input.amount-input:last')); // help FF return false; } else return true; } // Remove the add form's last posting row, if empty, keeping at least two. function addformDeletePosting() { var num = $('#addform tr.posting').length; if (num <= 2 || $('#addform tr.posting:last > td:first input:last').val() != '' ) return; // copy submit button var btn = $('#addform tr.posting:last > td:last').html(); // remember if the last row's field or button had focus var focuslost = $('#addform tr.posting:last > td:first input:last').is(':focus') || $('#addform tr.posting:last button').is(':focus'); // delete last row $('#addform tr.posting:last').remove(); // remember if the last amount field had focus focuslost = focuslost || $('#addform tr.posting:last > td:last input:last').is(':focus'); // replace new last row's amount field with the button $('#addform tr.posting:last > td:last').html(btn); // if deleted row had focus, focus the new last row if (focuslost) $('#addform tr.posting:last > td:first input:last').focus(); } function journalSelect(ev) { var textareas = $('textarea', $('form#editform')); for (i=0; i