Mercurial > pub > Impl
changeset 351:cfd7570c2af2
working on TTView: created TTView class for rendering models
author | cin |
---|---|
date | Tue, 08 Oct 2013 17:40:35 +0400 |
parents | f356c4894d1b |
children | 675cd1829255 |
files | Lib/IMPL/Web/View/TTContext.pm Lib/IMPL/Web/View/TTView.pm _test/Resources/view/layout/default.tt _test/Resources/view/layout/header.tt _test/Resources/view/packages/templates/ARRAY.tt _test/Resources/view/packages/templates/HASH.tt _test/Resources/view/packages/templates/plain.tt _test/Resources/view/site/product/view.tt _test/temp.pl |
diffstat | 9 files changed, 240 insertions(+), 90 deletions(-) [+] |
line wrap: on
line diff
--- a/Lib/IMPL/Web/View/TTContext.pm Mon Oct 07 17:35:54 2013 +0400 +++ b/Lib/IMPL/Web/View/TTContext.pm Tue Oct 08 17:40:35 2013 +0400 @@ -31,6 +31,7 @@ prefix cache includes + modules )) { my $t = $prop; @@ -66,6 +67,7 @@ my ($this,$name) = @_; my $cache = $this->tt_cache; + $this->tt_cache($cache = {}) unless $cache; if(my $tpl = $cache->{$name}) { @@ -77,7 +79,7 @@ my $ext = $this->tt_ext || ""; my $file; - + foreach my $dir (@inc) { $file = $dir ? "$dir/$name" : $name; @@ -85,15 +87,24 @@ $file = $ext ? "$file.$ext" : $file; - warn "lookup: $file"; - - my $tt = eval { $this->template($file) }; - - return $cache->{$name} = { - base => $base, - labels => $this->load_labels($file), - template => $tt, - } if $tt; + if (exists($this->modules->{$file})) { + my $info = $this->modules->{$file}; + return $cache->{$name} = $info + if $info; + } else { + if( my $tt = eval { $this->template($file) } ) { + my $info = { + base => $base, + labels => $this->load_labels($file), + template => $tt, + initialized => 0 + }; + $this->modules->{$file} = $info; + return $cache->{$name} = $info; + } else { + $this->modules->{$file} = undef; + } + } } $this->throw(Template::Constants::ERROR_FILE, "$name: not found"); @@ -113,9 +124,7 @@ my $prefix = $this->prefix; - warn "no resolve" if $args and $args->{_no_resolve}; - - if (not(($args and delete $args->{_no_resolve}) or ref $model)) { + if (not(($args and delete $args->{_no_resolve}) or ref $model)) { $prefix = $prefix ? "${prefix}.${model}" : $model; $model = $this->resolve_model($model); } else { @@ -136,6 +145,40 @@ ); } +sub display_model { + my $this = shift; + my $model = shift; + my ($template, $args); + + if (ref $_[0] eq 'HASH') { + $args = shift; + } else { + $template = shift; + $args = shift; + } + + $args ||= {}; + + my $prefix = delete $args->{prefix} || $this->prefix; + + if (my $rel = delete $args->{rel}) { + $prefix = $prefix ? "${prefix}.${rel}" : $rel; + } + + $template = $template ? $this->find_template($template) : $this->find_template_for($model); + + return $this->render( + $template, + hashApply( + { + prefix => $prefix, + model => $model, + }, + $args + ) + ); +} + sub invoke_environment { my ($this,$code,$env) = @_; @@ -146,13 +189,18 @@ hashApply( { root => $this->root || $this, + modules => $this->modules || {}, cache => TypeKeyedCollection->new(), display => sub { $this->display(@_); }, render => sub { $this->render(@_); - } + }, + display_model => sub { + $this->display_model(@_); + }, + tt_cache => {} }, $env ) @@ -174,29 +222,38 @@ $args ||= {}; - #TODO handle classes - - my ($base,$labels); - - $template = $this->find_template($template) unless ref $template; + my $info = ref $template ? $template : $this->find_template($template); - if (ref $template eq 'HASH') { - $base = $template->{base}; - $labels = $template->{labels}; - $template = $template->{template}; - } else { - carp "got an invalid template object: $template"; - $base = $this->base; + if (ref($info) ne 'HASH') { + carp "got an invalid template object: $info (" . ref($info) . ")"; + $info = { + template => $info, + base => $this->base, + initialized => 1 + }; } - return $this->invoke_environment( - sub { - return shift->include($template,$args); + return $this->invoke_environment( + sub { + my $ctx = shift; + + unless($info->{initialized}) { + if(my $init = $info->{template}->blocks->{INIT}) { + $info->{initialized} = 1; + eval { + $ctx->visit($info->{template}->blocks); + $ctx->include($init); + }; + $ctx->leave(); + } + } + + return $ctx->include($info->{template},$args); }, hashMerge( - $labels || {}, + $info->{labels} || {}, { - base => $base, + base => $info->{base}, parent => $this } )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/IMPL/Web/View/TTView.pm Tue Oct 08 17:40:35 2013 +0400 @@ -0,0 +1,78 @@ +package IMPL::Web::View::TTView; +use strict; + +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + Context => 'IMPL::Web::View::TTContext' + }, + base => [ + 'IMPL::Object' => undef, + 'IMPL::Object::Autofill' => '@_', + 'IMPL::Object::Serializable' => undef + ], + props => [ + options => PROP_RW, + view => PROP_RW, + layout => PROP_RW, + tt_ext => PROP_RW, + includes => PROP_RW | PROP_LIST + ] +}; + +sub CTOR { + my ($this) = @_; + + $this->tt_ext('tt') unless defined $this->tt_ext; +} + +sub display { + my ($this,$model,$template,$args) = @_; + + my $context = Context->new($this->options); + my $layout = delete $args->{layout}; + + return $context->invoke_environment( + sub { + my $ctx = shift; + if ($layout) { + return $ctx->invoke_environment( + sub { + return $ctx->render($layout,$args); + }, + { + base => $this->layout, + content => sub { + $ctx->invoke_environment( + sub { + return shift->display($model,$template,$args); + }, + { + base => $this->view + } + ) + } + } + ); + } else { + return $ctx->invoke_environment( + sub { + return $ctx->display($model,$template,$args); + }, + { + base => $this->view + } + ); + } + },{ + includes => scalar($this->includes), + tt_ext => 'tt', + document => {}, + debug => sub { + warn @_; + } + } + ); +} + +1; \ No newline at end of file
--- a/_test/Resources/view/layout/default.tt Mon Oct 07 17:35:54 2013 +0400 +++ b/_test/Resources/view/layout/default.tt Tue Oct 08 17:40:35 2013 +0400 @@ -1,5 +1,14 @@ -[% render('header') %] -[% render('menu') %] -[% render('nav') %] -$content -[% render('footer') %] \ No newline at end of file +[% + document.dojo.modules = []; +%] +[%~ WRAPPER DOC%] + $content +[% END %] + +[% BLOCK DOC %] + [%~ render('header') %] + [% render('menu') %] + [% render('nav') %] + $content + [% render('footer') %] +[% END %] \ No newline at end of file
--- a/_test/Resources/view/layout/header.tt Mon Oct 07 17:35:54 2013 +0400 +++ b/_test/Resources/view/layout/header.tt Tue Oct 08 17:40:35 2013 +0400 @@ -2,5 +2,18 @@ <html> <head> <title>$document.title</title> +<script> + [% + IF document.dojo.modules.size; + modules = []; + FOREACH module IN document.dojo.modules.unique; + modules.push('"' _ module _ '"'); + END; + %] + require([ [% modules.join(', ') %] ]); + [% + END; + %] +</script> </head> <body> \ No newline at end of file
--- a/_test/Resources/view/packages/templates/ARRAY.tt Mon Oct 07 17:35:54 2013 +0400 +++ b/_test/Resources/view/packages/templates/ARRAY.tt Tue Oct 08 17:40:35 2013 +0400 @@ -1,3 +1,3 @@ [% FOR item IN model %] - * ${loop.index}. [% display(item, { _no_resolve => 1, prefix => "$prefix[$loop.index]"}) %] + * ${loop.index}. [% display_model(item, prefix = "$prefix[$loop.index]") %] [% END %] \ No newline at end of file
--- a/_test/Resources/view/packages/templates/HASH.tt Mon Oct 07 17:35:54 2013 +0400 +++ b/_test/Resources/view/packages/templates/HASH.tt Tue Oct 08 17:40:35 2013 +0400 @@ -1,3 +1,3 @@ [% FOR item IN model %] - <div>$item.key : [% display(item.key) %]</div> + <div>$item.key : [% display_model(item.value, rel = item.key) %]</div> [% END %] \ No newline at end of file
--- a/_test/Resources/view/packages/templates/plain.tt Mon Oct 07 17:35:54 2013 +0400 +++ b/_test/Resources/view/packages/templates/plain.tt Tue Oct 08 17:40:35 2013 +0400 @@ -1,1 +1,6 @@ +[% + BLOCK INIT; + document.dojo.modules.push('diji/form/Textbox'); + END +%] <input name="$prefix">$model</input> \ No newline at end of file
--- a/_test/Resources/view/site/product/view.tt Mon Oct 07 17:35:54 2013 +0400 +++ b/_test/Resources/view/site/product/view.tt Tue Oct 08 17:40:35 2013 +0400 @@ -1,3 +1,4 @@ +[% document.title = PageTitle %] <h1> $PageTitle </h1> <div>name: [% display('name') %]</div> <div>description: [% display(model) %]</div> \ No newline at end of file
--- a/_test/temp.pl Mon Oct 07 17:35:54 2013 +0400 +++ b/_test/temp.pl Tue Oct 08 17:40:35 2013 +0400 @@ -2,59 +2,46 @@ use strict; use IMPL::require { - TTContext => 'IMPL::Web::View::TTContext' + TTView => 'IMPL::Web::View::TTView' }; -my $ctx = TTContext->new({ - INCLUDE_PATH => './Resources/view', - INTERPOLATE => 1, - RECURSION => 1000 -}); +use Time::HiRes qw(gettimeofday tv_interval); + +my $t = [gettimeofday]; + +my $view = TTView->new( + options => { + INCLUDE_PATH => './Resources/view', + INTERPOLATE => 1, + RECURSION => 1000 + }, + view => 'site', + layout => 'layout', + includes => [ + 'packages' + ] +); -print $ctx->invoke_environment(sub { - my ($this) = @_; - return $this->render( - 'default', - { - content => sub { - return $this->invoke_environment( - sub { - shift->render( - 'product/view', - { - model => { - name => 'debugger', - manufature => { - name => 'DEBUGGERS INC', - address => [ - { - coutry => 'Russuia', - city => 'Moscow' - }, - { - country => 'GB', - city => 'Essex' - } - ] - } - } - } - ); - }, { - base => 'site' - } - ); - } - } - ); -}, { - base => 'layout', - includes => [ - 'packages' - ], - tt_ext => 'tt', - document => { - title => 'Test document' - } -}); +print $view->display( + { + name => 'debugger', + manufacture => { + name => 'DEBUGGERS INC', + address => [ + { + coutry => 'Russuia', + city => 'Moscow' + }, + { + country => 'GB', + city => 'Essex' + } + ] + } + }, + 'product/view', + { layout => 'default' } +), "\n"; + +print "render page: ",tv_interval($t,[gettimeofday]),"ms\n";