File Coverage

blib/lib/JQuery/Treeview.pm
Criterion Covered Total %
statement 12 185 6.4
branch 0 58 0.0
condition 0 6 0.0
subroutine 4 21 19.0
pod 9 17 52.9
total 25 287 8.7


line stmt bran cond sub pod time code
1             package JQuery::Treeview ;
2              
3             our $VERSION = '1.01';
4              
5 1     1   932 use strict ;
  1         2  
  1         30  
6 1     1   6 use warnings ;
  1         19  
  1         27  
7              
8 1     1   978 use XML::Writer ;
  1         16190  
  1         27  
9 1     1   838 use IO::String ;
  1         2415  
  1         2535  
10              
11             sub new {
12 0     0 1   my $this = shift;
13 0   0       my $class = ref($this) || $this;
14 0           my $my ;
15 0           %{$my->{param}} = @_ ;
  0            
16 0 0         die "No id defined for Treeview" unless $my->{param}{id} =~ /\S/ ;
17              
18 0           my $jquery = $my->{param}{addToJQuery} ;
19 0           my $jqueryDir = $jquery->getJQueryDir ;
20 0           $my->{fileDir} = "$jqueryDir/plugins" ;
21 0 0         $my->{param}{separator} = "/" unless defined $my->{param}{separator} ;
22 0           bless $my, $class;
23 0           $my->add_to_jquery ;
24 0           return $my ;
25             }
26              
27             sub add_to_jquery {
28 0     0 0   my $my = shift ;
29 0           my $jquery = $my->{param}{addToJQuery} ;
30 0 0         if (defined $jquery) {
31 0           $jquery->add($my) ;
32             }
33             }
34              
35             sub id {
36 0     0 1   my $my = shift ;
37 0           return $my->{param}{id} ;
38             }
39              
40             sub type {
41 0     0 1   my $my = shift ;
42 0           return $my->{param}{type} ;
43             }
44              
45             sub treeControlId {
46 0     0 1   my $my = shift ;
47 0           return $my->{param}{treeControlId} ;
48             }
49              
50             sub debug {
51 0     0 0   my $my = shift ;
52 0           return $my->{param}{debug} ;
53             }
54              
55             sub defaultState {
56 0     0 1   my $my = shift ;
57 0           return $my->{param}{defaultState} ;
58             }
59              
60             sub highlightUnderline {
61 0     0 0   my $my = shift ;
62 0           return $my->{param}{highlightUnderline} ;
63             }
64              
65             sub packages_needed {
66 0     0 0   my $my = shift ;
67 0           return ('taconite/jquery.taconite.js','interface/interface.js','treeview/jquery.treeview.js','cookie/jquery.cookie.js') ;
68             }
69              
70             sub HTMLControl {
71 0     0 1   my $my= shift ;
72 0           my $treeControlText = $my->{param}{treeControlText} ;
73 0           my $treeControlId = $my->{param}{treeControlId} ;
74 0           my $html =<
75            
76             $treeControlText->[0]
77             $treeControlText->[1]
78             $treeControlText->[2]
79            
80             EOD
81 0           return $html ;
82             }
83              
84             sub HTML {
85 0     0 1   my $my= shift ;
86              
87 0           my $output = new IO::String;
88 0           $my->{writer} = new XML::Writer(OUTPUT => $output, DATA_INDENT=>1,DATA_MODE=>1,UNSAFE=>1 );
89              
90 0           my $id = $my->id ;
91 0           my $list = $my->{param}{list} ;
92 0           my $lastIndent = 0 ;
93 0           my @lines = split(/\n/,$list) ;
94 0           chomp @lines ;
95 0           my $type = $my->type ;
96 0           my $htmlResult ;
97 0           my $writer = $my->{writer} ;
98              
99 0 0         if ($type eq 'directory') {
100 0           $writer->startTag("ul", "id" => $id, "class" => "directory") ;
101             }
102 0 0         if ($type ne 'directory') {
103 0           $writer->startTag("ul", "id" => $id) ;
104             }
105              
106              
107 0           my @stack ;
108              
109 0           for my $line (@lines) {
110 0           my ($spaces) = $line =~ m!^(\s*)! ;
111 0           $line =~ s!^\s+!! ;
112 0           my $indent = length($spaces) ;
113 0           @stack = @stack[0..$indent-1] ;
114 0           $type = 'leaf' ;
115 0           my $state = '' ;
116 0           $my->closeNodes($indent) ;
117 0 0         if ($line =~ m!^(.*)(\([foc]+\))$!) {
118 0           $line = $1 ;
119 0           $line =~ s!\s+$$!! ;
120 0           my $options = $2 ;
121            
122 0 0         $state = 'closed' if $options =~ /c/ ;
123 0 0         $state = 'open' if $options =~ /o/ ;
124              
125 0           $type = 'node' ;
126 0           push @{$my->{stack}},"$indent $line" ;
  0            
127             }
128 0           push @stack,$line ;
129 0           $my->produce($line,$type,$state,\@stack) ;
130             }
131 0           $my->closeNodes(0) ;
132 0           $writer->endTag() ;
133 0           $writer->end();
134 0           my $htmlRef = $output->string_ref ;
135 0           my $html = $$htmlRef ;
136 0           $output->close();
137 0           return $html ;
138             }
139              
140             sub closeNodes {
141 0     0 0   my $my = shift ;
142 0           my $writer = $my->{writer} ;
143 0           my $n = shift ;
144 0 0         return if $n < 0 ;
145 0           while(1) {
146 0           my $pop = pop(@{$my->{stack}}) ;
  0            
147 0 0         last if ! defined $pop ;
148 0           my ($ind,$line) = split(' ',$pop,2) ;
149 0 0         if ($ind < $n) {
150 0           push @{$my->{stack}},$pop ;
  0            
151 0           last ;
152             }
153 0           $writer->endTag("ul");
154 0           $writer->endTag("li");
155             }
156             }
157              
158             sub produce {
159 0     0 0   my $my = shift ;
160 0           my $writer = $my->{writer} ;
161              
162 0           my $line = shift ;
163 0           my $nodeType = shift ;
164 0           my $state = shift ;
165 0           my $stack = shift ;
166 0           my $separator = $my->{param}{separator} ;
167            
168 0           my $stackLine = join($separator,grep {defined} @$stack) ;
  0            
169              
170 0           my $type = $my->type ;
171 0           my $highlightLeaves = $my->highlightLeaves ;
172 0           my $highlightNodes = $my->highlightNodes ;
173 0           my $defaultState = $my->defaultState ;
174              
175 0 0         if ($nodeType eq 'leaf') {
176 0           $writer->startTag("li");
177 0 0         $writer->emptyTag('img',src=>"$my->{fileDir}/treeview/images/file.gif", alt=>"file") if $type eq 'directory' ;
178 0           my $underline = '' ;
179            
180 0 0         $underline = "text-decoration: underline" if $my->highlightUnderline ;
181              
182 0 0         $writer->startTag('span',style=>"cursor: pointer; $underline") if $highlightLeaves ;
183 0           $writer->characters($line) ;
184 0 0         $writer->endTag('span') if $highlightLeaves ;
185 0           $writer->startTag('div', class => "hidden") ;
186 0           $writer->characters($stackLine) ;
187 0           $writer->endTag("div") ;
188 0           $writer->endTag("li") ;
189             }
190 0 0         if ($nodeType eq 'node') {
191 0 0 0       if (defined $state and $state eq $defaultState) {
192 0           $writer->startTag("li");
193             } else {
194 0           $writer->startTag("li", class=> $state);
195             }
196 0 0         $writer->emptyTag('img',src=>"$my->{fileDir}/treeview/images/folder.gif",alt=>"folder") if $type eq 'directory' ;
197 0           my $underline = '' ;
198 0 0         $underline = "text-decoration: underline" if $my->highlightUnderline ;
199              
200 0 0         $writer->startTag('span',style=>"cursor: pointer; $underline") if $highlightNodes ;
201 0           $writer->characters($line) ;
202 0 0         $writer->endTag('span') if $highlightNodes ;
203 0           $writer->startTag('div', class => "hidden") ;
204 0           $writer->characters($stackLine) ;
205 0           $writer->endTag("div") ;
206 0           $writer->startTag("ul");
207             }
208             }
209              
210             sub highlightLeaves {
211 0     0 1   my $my = shift ;
212 0           return $my->{param}{highlightLeaves} ;
213             }
214              
215             sub highlightNodes {
216 0     0 1   my $my = shift ;
217 0           return $my->{param}{highlightNodes} ;
218             }
219              
220             sub get_css {
221 0     0 0   my $my = shift ;
222 0           my $id = $my->id ;
223 0           my $type = $my->type ;
224             # generate the css according to the id name and type
225 0           my $css=<<'CSS';
226             .treeview, .treeview ul {
227             padding: 0;
228             margin: 0;
229             list-style: none;
230             }
231              
232             .treeview li {
233             margin: 0;
234             padding: 3px 0pt 3px 16px;
235             }
236            
237             ul.directory li { padding: 2px 0 0 16px; }
238            
239             CSS
240              
241 0           my $cssDir =<
242             #ID.treeview li { background: url($my->{fileDir}/treeview/images/tv-item.gif) 0 0 no-repeat; }
243             #ID.treeview .collapsable { background-image: url($my->{fileDir}/treeview/images/tv-collapsable.gif); }
244             #ID.treeview .expandable { background-image: url($my->{fileDir}/treeview/images/tv-expandable.gif); }
245             #ID.treeview .last { background-image: url($my->{fileDir}/treeview/images/tv-item-last.gif); }
246             #ID.treeview .lastCollapsable { background-image: url($my->{fileDir}/treeview/images/tv-collapsable-last.gif); }
247             #ID.treeview .lastExpandable { background-image: url($my->{fileDir}/treeview/images/tv-expandable-last.gif); }
248            
249             #treecontrol { margin: 1em 0; }
250              
251             CSS1
252 0           my $cssColor=<
253             #ID.treeview li { background: url($my->{fileDir}/treeview/images/TYPE/tv-item.gif) 0 0 no-repeat; }
254             #ID.treeview .collapsable { background-image: url($my->{fileDir}/treeview/images/TYPE/tv-collapsable.gif); }
255             #ID.treeview .expandable { background-image: url($my->{fileDir}/treeview/images/TYPE/tv-expandable.gif); }
256             #ID.treeview .last { background-image: url($my->{fileDir}/treeview/images/TYPE/tv-item-last.gif); }
257             #ID.treeview .lastCollapsable { background-image: url($my->{fileDir}/treeview/images/TYPE/tv-collapsable-last.gif); }
258             #ID.treeview .lastExpandable { background-image: url($my->{fileDir}/treeview/images/TYPE/tv-expandable-last.gif); }
259              
260             CSS2
261 0 0         if ($type eq 'directory') {
262 0           $cssDir =~ s/ID/$id/g ;
263 0           return $css . $cssDir ;
264             }
265 0 0         if ($type =~ /^(red|gray|black)$/) {
266 0           $cssColor =~ s/ID/$id/g ;
267 0           $cssColor =~ s/TYPE/$type/g ;
268 0           return $css . $cssColor ;
269              
270             }
271             }
272              
273             sub get_jquery_code {
274 0     0 0   my $my = shift ;
275 0           my $id = $my->id ;
276 0           my $remoteProgram = $my->{param}{remoteProgram} ;
277 0 0         return '' unless $id =~ /\S/ ;
278 0           my $treeControlId = $my->treeControlId ;
279 0           my $function1 =<<'EOD1';
280            
281             $("#ID").Treeview(TREE_CONTROL);
282             EOD1
283 0           my $treeControl = '' ;
284 0 0         if ($treeControlId =~ /\S/) {
285 0           $treeControl = qq[{ control: "#$treeControlId" }] ;
286             }
287 0           $function1 =~ s/TREE_CONTROL/$treeControl/ ;
288              
289 0           my $function2 =<<'EOD2';
290             $("#ID span").click(function(event) {
291             ALERT
292             $.post("PROGRAM_TO_RUN", { date: new Date().getTime(), data: $(this).text(), data1: $(this).next().text() RM } );
293             event.stopPropagation();
294             });
295             EOD2
296 0           my $function3=<<'EOD';
297             $(".hidden").hide() ;
298             EOD
299              
300 0           my $alert = q[alert('Button clicked ' + $(this).text())] ;
301 0 0         $alert = '' if $my->debug == 0 ;
302 0           $function2 =~ s/^\s*ALERT/$alert/m ;
303 0           $function1 =~ s/#ID/#$id/ ;
304 0           $function2 =~ s/#ID/#$id/ ;
305 0           $function2 =~ s/PROGRAM_TO_RUN/$remoteProgram/ ;
306 0           my $rm = ", rm: '$my->{param}{rm}'" ;
307 0 0         $rm = '' unless $my->{param}{rm} =~ /\S/ ;
308 0           $function2 =~ s/RM/$rm/ ;
309 0 0         $function2 = '' unless $remoteProgram =~ /\S/ ;
310 0           my $function4 = $my->dragAndDrop ;
311            
312 0           return $function1 . $function2 . $function3 . $function4 ;
313             }
314             1;
315             =head1 NAME
316              
317             JQuery::Treeview - shows a information as a tree.
318              
319             =head1 VERSION
320              
321             Version 1.00
322              
323             =cut
324              
325             =head1 SYNOPSIS
326              
327             JQuery::Treeview shows a information as a tree.
328              
329             use JQuery;
330             use JQuery::Treeview;
331              
332             my $list =<
333             folder 1(fc)
334             file 1.1
335             file 1.2
336             file 1.3
337             folder 1.2(f)
338             file 2.1
339             file 2.2
340             file 2.3
341             folder 1.3(fc)
342             folder 1.4(f)
343             file 1.4
344             folder 2(f)
345             file 2.1
346             folder 3(f)
347             EOD
348              
349             my $tree = JQuery::Treeview->new(list => $list,
350             id => 'mytree',
351             separator => "/",
352             addToJQuery => $jquery,
353             treeControlId => 'myTreeControl',
354             treeControlText => ['Collapse All','Expand All','Toggle All'],
355             defaultState => 'open',
356             highlightNodes => 1,
357             highlightLeaves => 1,
358             highlightUnderline => 1,
359             type => 'directory',
360             rm => 'MyTreeView',
361             debug => 0,
362             remoteProgram => '/cgi-bin/jquery_treeview_results.pl') ;
363             my $htmlControl = $tree->HTMLControl ;
364             my $html = $tree->HTML ;
365            
366             =head1 DESCRIPTION
367              
368             Treeview shows data in a tree format. For an example see L
369              
370             The simplest way to present the data is in the format shown
371             above. Each indentation represents another level. The letters in brackets stand for
372              
373             =over
374              
375             =item f
376              
377             A folder or node
378              
379             =item c
380              
381             The node is initially closed
382              
383             =item o
384              
385             The node is initially open
386              
387             =back
388              
389             (Putting all this information in a Perl array with embedded hashes is
390             possible, but really ugly, and hard to debug visually. I tried, but didn't like the result.)
391              
392             The other parameters are:
393              
394             =over
395              
396             =item list
397              
398             The list in the format show above
399              
400             =item id
401              
402             The css id of the element
403              
404             =item separator
405              
406             When an item is pressed, the it and all ancestors are concatenated and
407             sent to the calling program. The item called 'data' contains just the
408             data as shown at the leaf or node. 'data1' gives the whole path, each
409             element being separated by the separator.
410              
411             In other words, you might get data=myfile, and data1=dir/dir1/dir2/myfile
412              
413             =item addToJQuery
414              
415             The JQuery container
416              
417             =item treeControlId
418              
419             The id of a control element. JQuery::Treeview can
420             generate the control HTML, which is just a set of links allowing the
421             user to manipulate the tree. The user can collapse all, expand all, and toggle all.
422              
423             =item treeControlText
424              
425             These are the text items needed for the treeControlId
426              
427             =item defaultState
428              
429             The default state of the tree, either open or closed.
430              
431             =item highlightNodes
432              
433             If highlightNodes is set, then nodes will be underlined
434              
435             =item highlightLeaves
436              
437             If highlightLeaves is set, then the leaves will be underlined
438              
439             =item type
440              
441             If type is 'directory', the folder and file icons will be used in the display.
442             If the type is gray, red or black no icons are used.
443              
444             =item rm
445              
446             This is the runmode to be used when running an external program
447              
448             =item remoteProgram
449              
450             This is the name of the remote program to be used when an item is pressed.
451              
452             =back
453              
454             =head1 FUNCTIONS
455              
456             =over
457              
458             =item new
459              
460             Instantiate the object.
461              
462             =item HTML
463              
464             Produce the HTML code
465              
466             =item HTMLControl
467              
468             Produce the HTML code for the control
469              
470             =back
471              
472             =head1 AUTHOR
473              
474             Peter Gordon, C<< >>
475              
476             =head1 BUGS
477              
478             Please report any bugs or feature requests to
479             C, or through the web interface at
480             L.
481             I will be notified, and then you'll automatically be notified of progress on
482             your bug as I make changes.
483              
484             =head1 SUPPORT
485              
486             You can find documentation for this module with the perldoc command.
487              
488             perldoc JQuery
489              
490             You can also look for information at:
491              
492             =over 4
493              
494             =item * AnnoCPAN: Annotated CPAN documentation
495              
496             L
497              
498             =item * CPAN Ratings
499              
500             L
501              
502             =item * RT: CPAN's request tracker
503              
504             L
505              
506             =item * Search CPAN
507              
508             L
509              
510             =back
511              
512             =head1 ACKNOWLEDGEMENTS
513              
514             =head1 COPYRIGHT & LICENSE
515              
516             Copyright 2007 Peter Gordon, all rights reserved.
517              
518             This program is free software; you can redistribute it and/or modify it
519             under the same terms as Perl itself.
520              
521             =cut
522              
523             1; # End of JQuery::Treeview
524