Dancer2-Plugin-Growler

 view release on metacpan or  search on metacpan

lib/Dancer2/Plugin/Growler.pm  view on Meta::CPAN

    $_[2]->{type} = 'success';
    goto &_growl;
};

register growl_warning => sub {
    $_[2]->{type} = 'warning';
    goto &_growl;
};

register growl_error => sub {
    $_[2]->{type} = 'danger';
    goto &_growl;
};

register growls => sub {
    my $dsl = shift;
    return if !$dsl->app->session->read('growls');
    my @growls = @{ $dsl->app->session->read('growls') };
    $dsl->app->session->write( 'growls', [] );
    return \@growls;
};

on_plugin_import {
    my $dsl = shift;

    # TODO 2: Is there a better way to add template keyword?
    $dsl->app->add_hook(

        # ?TODO/YAGNI? do growl() and growl_*() in TT also?
        Dancer2::Core::Hook->new(
            name => 'before_template_render',
            code => sub {
                $_[0]->{growls} = sub { $dsl->growls(@_) }
            },
        )
    );
};

register_plugin;

1;

__END__

=encoding utf-8

=head1 NAME

Dancer2::Plugin::Growler - Growl multiple messages of varying types to the user on their next hit.

=head1 VERSION

This document describes Dancer2::Plugin::Growler version 0.03

=head1 SYNOPSIS

    use Dancer2::Plugin::Growler;

    …

    my $error = locale->maketext('Invalid login credentials.'); # locale() is from L<Dancer2::Plugin::Locale>
    growl_error($error); 
    redirect '/login';

    …

    my $msg = locale->maketext('Successfully created post the post “[_1]”.', $html_safe_title); # locale() is from L<Dancer2::Plugin::Locale>
    growl_success($msg); 
    redirect "/post/$new_id";

Then in the view’s layout (this example implies a bootstrap3/jquery environment w/ the bootstrapGrowl jquery plugin):

    [% SET growl_list = growls() %]
    [%- IF growl_list.size %]
    [% USE JSON.Escape %]
    <script type="text/javascript">
        $( document ).ready(function() {
            [% FOREACH growl in growl_list -%]
                $.bootstrapGrowl("[% growl.message.dquote %]", [% growl.options.json %]);
            [% END %]
        });
    </script>
    [%- END %]

=head1 DESCRIPTION

This allows you to specify one or more one-time messages (of varying types) to growl on the user’s next hit (or this hit if you render a view that implements it) with out needing to pass around parameters.

It is also a nice approach because it is refresh safe. For example, in the SYNOPSIS example with the blog post, say we rendered the message at the end of the request instead: refreshing the page could cause us to post the blog article again.

It is similar to the “flash” example in the Dancer2 documentation but without the multi-user race condition and limitation of one message.

It is also AJAX-safe (don’t call growls() in your AJAX templates and you won’t miss any message) yet still AJAX-able (call growls() in your AJAX templates in order to include them in your response).

Also, with this approach your perl can growl exactly like you do in JavaScript with zero effort. Ease of Consistency FTW!

=head1 INTERFACE 

=over 4

=item growl()

The first argument is the message to growl. The second, optional argument is hashref of arguments.

The keys it can specify are:

=over 4

=item 'type'

The type of message. The values, if given, can be: 'info', 'success', 'warning', or 'danger' (That last one is from bootstrap convention).

If your javascript implementation uses a different key (or different values) for this then your system will need to factor that in.

=item 'delay'

The number of milliseconds you intend the growl to display before fading out.

Zero should cause your JavaScript implementation to not fade, effectively making it permanent.

If your JavaScript implementation uses a different key for this then your system will need to factor that in.



( run in 1.986 second using v1.01-cache-2.11-cpan-140bd7fdf52 )