Chart-Dygraphs

 view release on metacpan or  search on metacpan

lib/Chart/Dygraphs.pm  view on Meta::CPAN

package Chart::Dygraphs;

use strict;
use warnings;
use utf8;

use Exporter 'import';
our @EXPORT_OK = qw(show_plot);

use JSON;
use Params::Validate qw(:all);
use Text::Template;
use HTML::Show;
use Ref::Util;

our $VERSION = '0.007';    # VERSION

# ABSTRACT: Generate html/javascript charts from perl data using javascript library Dygraphs

sub render_full_html {
    my %params = validate( @_,
                           {  data    => { type => SCALAR | ARRAYREF | OBJECT },
                              options => { type => HASHREF, default => { showRangeSelector => 1 } },
                              render_html_options => { type     => HASHREF,
                                                       optional => 1,
                                                       default  => {}
                              }
                           }
    );
    return _render_html_wrap(
           _render_cell( _process_data_and_options( @params{qw(data options)} ), $params{'render_html_options'}, '' ) );
}

sub _transform_data {
    my $data        = shift;
    my $string_data = "";
    if ( Ref::Util::is_plain_arrayref($data) ) {
        $string_data .= "[" . ( join( ',', map { _transform_data($_) } @$data ) ) . "]";
    } elsif ( Ref::Util::is_plain_hashref($data) ) {
        return "not supported";
    } elsif ( Ref::Util::is_blessed_ref($data) && $data->isa('DateTime') ) {
        return 'new Date("' . $data . '")';
    } else {
        return $data;
    }
    return $string_data;
}

sub _process_data_and_options {
    my $data           = shift();
    my $options        = shift();
    my $json_formatter = JSON->new->utf8;
    local *PDL::TO_JSON = sub { $_[0]->unpdl };
    if ( Ref::Util::is_blessed_ref($data) ) {
        my $adapter_name = 'Chart::Dygraphs::Adapter::' . ref $data;
        eval {
            load $adapter_name;
            my $adapter = $adapter_name->new( data => $data );
            $data = $adapter->series();
        };
        if ($@) {
            warn 'Cannot load adapter: ' . $adapter_name . '. ' . $@;
        }
    }
    return join( ',', _transform_data($data), $json_formatter->encode($options) );
}

sub _render_cell {

    my $data         = shift();
    my $html_options = shift();
    my $id           = shift();
    my $template     = <<'TEMPLATE';
{$pre_graph_html}
<div id="{$dygraphs_div_id}" style="{$dygraphs_div_inline_style}"></div>
<script type="text/javascript">
  {$dygraphs_javascript_object_name} = new Dygraph(
    document.getElementById("{$dygraphs_div_id}"),
    {$data_and_options}
  );

  var range = {$dygraphs_javascript_object_name}.yAxisRange(0);
  {$dygraphs_javascript_object_name}.updateOptions(\{valueRange: range\});
</script>
{$post_graph_html}
TEMPLATE
    my $template_variables = { %{$html_options}, data_and_options => $data, };

    if ( !defined $template_variables->{'dygraphs_div_id'} ) {
        $template_variables->{'dygraphs_div_id'} = 'graphdiv' . $id;
    }
    if ( !defined $template_variables->{'dygraphs_javascript_object_name'} ) {
        $template_variables->{'dygraphs_javascript_object_name'} = 'g' . $id;
    }
    if ( !defined $template_variables->{'dygraphs_div_inline_style'} ) {
        $template_variables->{'dygraphs_div_inline_style'} = 'width: 100%';
    }
    my $renderer = Text::Template->new( TYPE => 'STRING', SOURCE => $template );
    return $renderer->fill_in( HASH => $template_variables );
}

sub _render_html_wrap {
    my $body = shift();

    my $html_begin = <<'BEGIN_HTML';
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dygraph/1.1.1/dygraph-combined.js"></script>
</head>
<body>
BEGIN_HTML

    my $html_end = <<'END_HTML';
</body>



( run in 1.604 second using v1.01-cache-2.11-cpan-39bf76dae61 )