packages feed

hledger-web-1.50: templates/chart.hamlet

$# If $ is the first character in a line, it must be \-escaped to hide it from hamlet.
<label #register-chart-label style=""><br>
<div #register-chart style="height:150px; margin-bottom:1em; display:block;">
<script type=text/javascript>
  \$(document).ready(function() {
    var $chartdiv = $('#register-chart');
    if ($chartdiv.is(':visible')) {
      \$('#register-chart-label').text('#{charttitle}');
      var seriesData = [
      $forall (c,items) <- percommoditytxnreports
        // we render each commodity using two series:
        // one with extra data points added to show a stepped balance line
        {
        data: [
          $forall i <- reverse items
            [
            #{dayToUtcNoonTimestamp $ triDate i},
            #{simpleMixedAmountQuantity $ triCommodityBalance c i}
            ],
        ],
        label: '#{shownull $ T.unpack c}',
        color: #{colorForCommodity c},
        lines: {
          show: true,
          steps: true,
        },
        points: {
          show: false,
        },
        clickable: false,
        hoverable: false,
        },
        // and one with the original data, showing one clickable, hoverable point per transaction
        {
        data: [
          $forall i <- reverse items
            [
            #{dayToUtcNoonTimestamp $ triDate i},
            #{simpleMixedAmountQuantity $ triCommodityBalance c i},
            '#{showZeroCommodity $ triCommodityAmount c i}',
            '#{showZeroCommodity $ triCommodityBalance c i}',
            '#{concat $ intersperse "\\n" $ lines $ T.unpack $ showTransaction $ triOrigTransaction i}',
            #{tindex $ triOrigTransaction i}
            ],
        ],
        label: '',
        color: #{colorForCommodity c},
        lines: {
          show: false,
        },
        points: {
          show: true,
        },
        },
      ];
      var plot = registerChart($chartdiv, seriesData);
      plot.setSelection({ xaxis: { from: 500, to: 700 } });  // ?
      \$chartdiv.bind("plotclick",    registerChartClick);
      \$chartdiv.bind("plotselected", registerChartSelect);
    };
  });

  //eslint-disable-next-line no-unused-vars
  function registerChart($container, series) {
    // https://github.com/flot/flot/blob/master/API.md
    return $container.plot(
      series,
      {
        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");
  }

  // Handle a click event on the chart.
  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);
    }
  }

  // Handle a selection (zoom) event on the chart.
  function registerChartSelect(ev, ranges) {
    console.log("selected", ranges.xaxis.from, ranges.xaxis.to);

    // Reconstruct from/to dates carefully based on the selected x-values.
    // Those x values are unix timestamps (milliseconds since epoch) enclosing the data points' timestamps.
    // Those are generated by dayToJsTimestamp, and are UTC times representing the transaction dates.
    var from = new Date(ranges.xaxis.from);
    var fromy = from.getUTCFullYear();
    var fromm = from.getUTCMonth() + 1;
    var fromd = from.getUTCDate();
    var to = new Date(ranges.xaxis.to + 1 * 24 * 60 * 60 * 1000);
    var toy = to.getUTCFullYear();
    var tom = to.getUTCMonth() + 1;
    var tod = to.getUTCDate();

    var range = fromy + "/" + fromm + "/" + fromd + "-" + toy + "/" + tom + "/" + tod;
    var baselink = "@?{nodatelink}";
    if (baselink.endsWith("?q")) {
      document.location = baselink + "=date:" + range;
    } else {
      document.location = baselink + "%20date:" + range;
    }
  }