comparison Lib/IMPL/Web/View/TTControl.pm @ 299:bd79145657e5

sync
author sergey
date Thu, 21 Mar 2013 16:00:09 +0400
parents 86ff93b34f2a
children bf3af33b9003
comparison
equal deleted inserted replaced
298:78f767765706 299:bd79145657e5
1 package IMPL::Web::View::TTControl; 1 package IMPL::Web::View::TTControl;
2 use strict; 2 use strict;
3 3
4 use IMPL::Const qw(:prop); 4 use IMPL::Const qw(:prop);
5 use IMPL::lang qw(:hash); 5 use IMPL::lang qw(:hash);
6 use Scalar::Util qw(blessed); 6 use Scalar::Util qw(blessed reftype);
7 use IMPL::declare { 7 use IMPL::declare {
8 require => { 8 require => {
9 TemplateDocument => 'Template::Document', 9 TemplateDocument => 'Template::Document',
10 TTContext => 'Template::Context', 10 TTContext => 'Template::Context',
11 Exception => 'IMPL::Exception', 11 Exception => 'IMPL::Exception',
16 'IMPL::Object' => undef 16 'IMPL::Object' => undef
17 ], 17 ],
18 props => [ 18 props => [
19 id => PROP_RO, 19 id => PROP_RO,
20 attributes => PROP_RW, 20 attributes => PROP_RW,
21 name => PROP_RO,
22 context => PROP_RO, 21 context => PROP_RO,
23 template => PROP_RO 22 template => PROP_RO
24 ] 23 ]
25 }; 24 };
26 25
27 26
28 { 27 {
29 my $nextId = 1; 28 my $nextId = 1;
30 sub _GetNextId { 29 sub _GetNextId {
31 return $nextId++; 30 return '_' . $nextId++;
32 } 31 }
33 } 32 }
34 33
35 our $AutoloadRegex = qr/^[a-z]/; 34 our $AutoloadRegex = qr/^[a-z]/;
36 our @REFLECT_META = qw(title layout);
37 35
38 sub CTOR { 36 sub CTOR {
39 my ($this,$name,$template,$context,$refProps) = @_; 37 my ($this,$template,$context,$attrs) = @_;
40 38
41 $name ||= "control"; 39
42
43 $this->template( $template ) or die new IMPL::ArgumentException("A template is required"); 40 $this->template( $template ) or die new IMPL::ArgumentException("A template is required");
44 $this->context( $context ) or die new IMPL::ArgumentException("A context is required"); 41 $this->context( $context ) or die new IMPL::ArgumentException("A context is required");
45 42
46 $this->id($name . "-" . _GetNextId()) unless $this->id;
47
48 $this->name($name);
49 $this->attributes({}); 43 $this->attributes({});
50 44
51 my %attrs; 45 if(reftype($attrs) eq 'HASH') {
52 46 while (my($key,$value) = each %$attrs) {
53 foreach my $meta ( @REFLECT_META ) { 47 $this->SetAttribute($key,$value);
54 next if $meta =~ /^_/; 48 }
55 if( my $value = $template->$meta() ) { 49 }
56 $attrs{$meta} = $value; 50
57 } 51 $this->id(_GetNextId()) unless $this->id;
58 }
59
60 hashApply(\%attrs,$refProps) if ref $refProps eq 'HASH';
61
62 while (my($key,$value) = each %attrs) {
63 $this->SetAttribute($key,$value);
64 }
65 }
66
67 sub InitInstance {
68 my ($this,$args) = @_;
69
70 $args ||= {};
71
72 if ( my $ctor = $this->template->blocks->{CTOR} ) {
73 $this->context->include($ctor, { %$args, this => $this, template => $this->template } );
74 }
75 } 52 }
76 53
77 sub GetAttribute { 54 sub GetAttribute {
78 my ($this,$name) = (shift,shift); 55 my ($this,$name) = (shift,shift);
79 56
95 } else { 72 } else {
96 return $this->attributes->{$name} = shift; 73 return $this->attributes->{$name} = shift;
97 } 74 }
98 } 75 }
99 76
100 sub GetMainBlock {
101 $_[0]->template->blocks->{RENDER} || $_[0]->template;
102 }
103
104 sub Render { 77 sub Render {
105 my ($this,$args) = @_; 78 my ($this,$args) = @_;
106 79
107 $args = {} unless ref $args eq 'HASH'; 80 $args = {} unless ref $args eq 'HASH';
108 81
109 if(my $body = $this->GetMainBlock ) { 82 return $this->context->include(
110 return $this->context->include( $body, { %$args, this => $this, template => $this->template } ); 83 $this->template,
111 } else { 84 {
112 return ""; 85 %$args,
113 } 86 this => $this,
114 } 87 template => $this->template
115 88 }
116 sub RenderBlock { 89 );
117 my ($this, $block, $args) = @_;
118
119 $args = {} unless ref $args eq 'HASH';
120
121 return $block ? $this->context->include( $block, { %$args, this => $this, template => $this->template } ) : undef;
122 }
123
124 sub ExportBlock {
125 my ($this,$block) = @_;
126
127 return TemplateDocument->new({
128 BLOCK => $this->template->blocks->{$block},
129 DEFBLOCKS => $this->template->blocks
130 });
131 } 90 }
132 91
133 sub AUTOLOAD { 92 sub AUTOLOAD {
134 our $AUTOLOAD; 93 our $AUTOLOAD;
135 94
164 123
165 [% 124 [%
166 META version = 1; 125 META version = 1;
167 BLOCK INIT; 126 BLOCK INIT;
168 # this is a document scope 127 # this is a document scope
169 dojo.require.push( 'dijit/form/Input' ); 128 dojo.modules.push( 'dijit/form/Input' );
170 END; 129 END;
171 BLOCK CTOR; 130
172 # local to this block 131 # local to this block
173 TPreview = require('My/Org/TextPreview'); 132 TPreview = require('My/Org/TextPreview');
174 133
175 # init control props 134 # init control props
176 this.dojoClass = this.dojoClass || 'dijit.form.Input'; 135 visualClass = this.visualClass || 'classic';
177 this.visualClass = this.visualClass || 'classic'; 136 %]
178 this.childNodes = []; 137 <div id="$id" class="$visualClass" data-dojo-type="dijit/form/Input">
179 138 [% FOREACH item IN model %]
180 # init content 139 <div class="itemContainer">
181 FOREACH text IN this.data; 140 [% Display(item) %]
182 this.childNodes.push( TPreview.new('preview', nodeValue = text ) ); 141 </div>
183 END;
184
185 END;
186 %]
187
188 <div class="$this.visualClass" data-dojo-type="$this.dojoClass">
189 [% FOREACH node IN this.childNodes %]
190 [% node.Render() %]
191 <hr />
192 [% END %] 142 [% END %]
193 </div> 143 </div>
194 144
195 =end text 145 =end text
196 146
197 =head1 DESCRIPTION 147 =head1 DESCRIPTION
198 148
199 Представляет собой фрагмент документа, который имеет шаблон для отображения, 149 Легкая обертка вокруг шаблона, позволяет изолировать пространство имен шаблона,
200 набор свойств и т.п. 150 а также реализовать собственные методы по представлению данных (в случае если
151 это проще сделать в виде методов класса).
201 152
202 =head2 BLOCKS 153 =head2 BLOCKS
203 154
204 =head3 META 155 =head3 META
205 156