File Coverage

blib/lib/Catalyst/View/TT/Progressive.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package Catalyst::View::TT::Progressive;
2              
3 1     1   66079 use strict;
  1         2  
  1         28  
4 1     1   5 use warnings;
  1         2  
  1         23  
5              
6 1     1   598 use Moose; # Catalyst::View;
  1         479837  
  1         7  
7             extends 'Catalyst::View::TT';
8             our $VERSION = '0.01';
9              
10             around 'render' => sub {
11             my ($meth, $orig, $c, $template, $args) = (@_, $_[2]->stash());
12             my ($wrapper, $ext) = (
13             ($args->{WRAPPER} || $c->req->header($orig->config->{WRAPPER_HEADER} || 'WRAPPER') || $orig->config->{WRAPPER}),
14             ($orig->config->{TEMPLATE_EXTENSION} || '.tt')
15             );
16             $wrapper .= $ext unless (!$wrapper || $wrapper =~ m/\Q$ext\E/);
17             $orig->{template}->{SERVICE}->{WRAPPER} = ($args->{NO_WRAPPER} || $c->req->header($orig->config->{NO_WRAPPER_HEADER} || 'NO_WRAPPER'))
18             ? []
19             : [$wrapper];
20             $orig->$meth($c, $template, $args);
21             };
22              
23             1;
24              
25             __END__
26              
27             =head1 NAME
28              
29             Catalyst::View::TT::Progressive - Control the wrapper
30              
31             =head1 VERSION
32              
33             Version 0.01
34              
35             =cut
36              
37             =head1 SYNOPSIS
38              
39             package MyApp::View::HTML;
40              
41             use Moose;
42             extends 'Catalyst::View::TT::Progressive';
43              
44             __PACKAGE__->config(
45             TEMPLATE_EXTENSION => '.tt',
46             INCLUDE_PATH => [
47             MyApp->path_to('root', 'templates'),
48             ],
49             TIMER => 0,
50             WRAPPER => 'wrapper.tt',
51             WRAPPER_HEADER => 'WRAPPER',
52             NO_WRAPPER_HEADER => 'NO_WRAPPER'
53             );
54              
55             1;
56              
57             === wrapper.tt ===
58              
59             <!doctype html>
60             <html lang="en">
61             <head>
62             <meta charset="utf-8">
63             <meta name="viewport" content="width=device-width, initial-scale=1.0">
64             <meta name="description" content="A layout example with a side menu that hides on mobile, just like the Pure website.">
65             <title>Responsive Side Menu &ndash; Layout Examples &ndash; Pure</title>
66              
67             <link rel="stylesheet" href="/static/css/pure-min.css" integrity="sha384-" crossorigin="anonymous">
68             <!--[if lte IE 8]>
69             <link rel="stylesheet" href="css/layouts/side-menu-old-ie.css">
70             <![endif]-->
71             <!--[if gt IE 8]><!-->
72             <link rel="stylesheet" href="/static/css/layouts/side-menu.css">
73             <!--<![endif]-->
74             </head>
75             <body>
76             <div id="layout">
77             <!-- Menu toggle -->
78             <a href="#menu" id="menuLink" class="menu-link">
79             <!-- Hamburger icon -->
80             <span></span>
81             </a>
82             <div id="menu">
83             <div class="pure-menu">
84             <a class="pure-menu-heading" href="#">Company</a>
85              
86             <ul class="pure-menu-list">
87             <li class="pure-menu-item pure-menu-selected"><a href="[% c.uri_for('/') %]" class="pure-menu-link">Home</a></li>
88             <li class="pure-menu-item"><a href="[% c.uri_for('/one') %]" class="pure-menu-link">One</a></li>
89             <li class="pure-menu-item menu-item-divided">
90             <a href="[% c.uri_for('/two') %]" class="pure-menu-link">Two</a>
91             </li>
92             <li class="pure-menu-item"><a href="[% c.uri_for('/three') %]" class="pure-menu-link">Three</a></li>
93             </ul>
94             </div>
95             </div>
96             <div id="main" progressive>
97             [% content %]
98             </div>
99             </div>
100             <script src="/static/js/app.js"></script>
101             </body>
102             </html>
103              
104             === Your app.js ===
105              
106             // A naive implementation
107             (function () {
108             var progressive = {
109             menu: document.getElementById('menu'),
110             request: function (url, cb, ecb) {
111             if (url.match('^#')) return;
112             var request = new XMLHttpRequest();
113             request.onreadystatechange = function () {
114             if (request.readyState === XMLHttpRequest.DONE) request.status === 200 ? cb(request.response) : ecb(request);
115             };
116             request.open('GET', url);
117             request.setRequestHeader('WRAPPER', 'new_wrapper.tt');
118             request.send();
119             }
120             render: function (res) {
121             var wrapper = document.querySelector('[progressive]');
122             wrapper.innerHTML = res;
123             },
124             error: function (req) {}
125             };
126              
127             window.addEventListener('click', function (event) {
128             if (event.target.tagName === 'A') {
129             event.preventDefault();
130             progressive.request(event.target.href, progressive.render, progressive.error);
131             }
132             });
133              
134             document.querySelectorAll('.pure-menu-link').forEach(function (link) {
135             link.addEventListener('click', function (event) {
136             progressive.menu.querySelector('.pure-menu-selected').classList.remove('pure-menu-selected');
137             event.target.parentNode.classList.add('pure-menu-selected');
138             });
139             });
140              
141             ....
142              
143             })();
144            
145             L<https://developers.google.com/web/progressive-web-apps/>
146              
147             =head1 AUTHOR
148              
149             LNATION, C<< <thisusedtobeanemail at gmail.com> >>
150              
151             =head1 BUGS
152              
153             Please report any bugs or feature requests to C<bug-catalyst-view-tt-progressive at rt.cpan.org>, or through
154             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-View-TT-Progressive>. I will be notified, and then you'll
155             automatically be notified of progress on your bug as I make changes.
156              
157             =head1 SUPPORT
158              
159             You can find documentation for this module with the perldoc command.
160              
161             perldoc Catalyst::View::TT::Progressive
162              
163             You can also look for information at:
164              
165             =over 4
166              
167             =item * RT: CPAN's request tracker (report bugs here)
168              
169             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-View-TT-Progressive>
170              
171             =item * AnnoCPAN: Annotated CPAN documentation
172              
173             L<http://annocpan.org/dist/Catalyst-View-TT-Progressive>
174              
175             =item * CPAN Ratings
176              
177             L<http://cpanratings.perl.org/d/Catalyst-View-TT-Progressive>
178              
179             =item * Search CPAN
180              
181             L<http://search.cpan.org/dist/Catalyst-View-TT-Progressive/>
182              
183             =back
184              
185              
186             =head1 ACKNOWLEDGEMENTS
187              
188              
189             =head1 LICENSE AND COPYRIGHT
190              
191             Copyright 2019 LNATION.
192              
193             This program is free software; you can redistribute it and/or modify it
194             under the terms of the the Artistic License (2.0). You may obtain a
195             copy of the full license at:
196              
197             L<http://www.perlfoundation.org/artistic_license_2_0>
198              
199             Any use, modification, and distribution of the Standard or Modified
200             Versions is governed by this Artistic License. By using, modifying or
201             distributing the Package, you accept this license. Do not use, modify,
202             or distribute the Package, if you do not accept this license.
203              
204             If your Modified Version has been derived from a Modified Version made
205             by someone other than you, you are nevertheless required to ensure that
206             your Modified Version complies with the requirements of this license.
207              
208             This license does not grant you the right to use any trademark, service
209             mark, tradename, or logo of the Copyright Holder.
210              
211             This license includes the non-exclusive, worldwide, free-of-charge
212             patent license to make, have made, use, offer to sell, sell, import and
213             otherwise transfer the Package with respect to any patent claims
214             licensable by the Copyright Holder that are necessarily infringed by the
215             Package. If you institute patent litigation (including a cross-claim or
216             counterclaim) against any party alleging that the Package constitutes
217             direct or contributory patent infringement, then this Artistic License
218             to you shall terminate on the date that such litigation is filed.
219              
220             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
221             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
222             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
223             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
224             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
225             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
226             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
227             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
228              
229              
230             =cut
231              
232             1; # End of Catalyst::View::TT::Progressive