File Coverage

blib/lib/HTML/ListToTree/DTree.pm
Criterion Covered Total %
statement 46 46 100.0
branch 10 14 71.4
condition 7 13 53.8
subroutine 12 12 100.0
pod 0 9 0.0
total 75 94 79.7


line stmt bran cond sub pod time code
1             =pod
2              
3             =begin classdoc
4              
5             Implements the HTML::ListToTree widget using the dtree software.
6             Contains the dtree software, stylesheet, and icons.

7              
8             The dtree widget software and components included in this
9             package are distributed in accordance
10             with the following license and copyright:
11            
 
12             /*--------------------------------------------------|
13             | dTree 2.05| www.destroydrop.com/javascripts/tree/ |
14             |---------------------------------------------------|
15             | Copyright (c) 2002-2003 Geir Landrö |
16             | |
17             | This script can be used freely as long as all |
18             | copyright messages are intact. |
19             | |
20             | Updated: 17.04.2003 |
21             |--------------------------------------------------*/
22            
23              
24             @author Dean Arnold
25             @since 2007-Jun-10
26             @self $self
27              
28             =end classdoc
29              
30             =cut
31              
32             package HTML::ListToTree::DTree;
33              
34 1     1   7 use MIME::Base64;
  1         2  
  1         70  
35              
36 1     1   11 use strict;
  1         2  
  1         35  
37 1     1   5 use warnings;
  1         2  
  1         1236  
38              
39             our $VERSION = '1.01';
40              
41             our %dtree_images = (
42             'base.gif' =>
43             'R0lGODlhFQASAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD/
44             /////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
45             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBm
46             AABmMwBmZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/
47             MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNm
48             ZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/
49             mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZm
50             zGZm/2aZAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb/
51             /5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZ
52             AJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwA
53             M8wAZswAmcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZ
54             ZsyZmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8A
55             mf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+Z
56             zP+Z///MAP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP///ywAAAAAFQASAAAInAAfCBxI
57             sKDBgqMOKiSICpaohQoBzHkwrRDBP6hQLQRgSaDGB6gePvizUY5AaqJIClwwCgCAgwAuDQQw7cEC
58             jw8uvSwocaazgQtIztlJMOZMWDYFWhxqkONMakAJPWDK06RAmkkfJLREdKaliQ8A/BQoqqacrjPn
59             yMQ6itBYrhFNAijkp+ZAqjDnyLn0da/asxBdCh7sEqLhw4cDAgA7
60             ',
61             'closedbook.gif' =>
62             'R0lGODlhFgAUAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD/
63             /////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
64             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBm
65             AABmMwBmZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/
66             MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNm
67             ZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/
68             mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZm
69             zGZm/2aZAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb/
70             /5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZ
71             AJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwA
72             M8wAZswAmcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZ
73             ZsyZmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8A
74             mf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+Z
75             zP+Z///MAP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP///yH5BAEAABAALAAAAAAWABQA
76             AAiVAP8JHEiwoMGDCBMiRIFC4UIUl+Q0dDiQoaWIlixNVMhwjpw5luaI1MgR1qWLITOCnLPRIApL
77             1D6CvLSSZkuCKOZcmgbyoxyMIG8KzBmS2smTM+VoFJrzpxxqHn+KZIhqYcpLRiMyJPTPT8KcEedM
78             2+rsnzOGX39q9Fp2rNCCTRvC+oeWIt1LKFDVtTt0L9+/gANTDAgAOw==
79             ',
80             'empty.gif' =>
81             'R0lGODlhEgASAJEAAAAAAP///4CAgP///yH5BAEAAAMALAAAAAASABIAAAIPnI+py+0Po5y02ouz
82             3pwXADs=
83             ',
84             'folder.gif' =>
85             'R0lGODlhEgASANUAAPv7++/v79u3UsyZNOTk5MHBwaNxC8KPKre3t55sBrqHIpxqBMmWMb2KJbOB
86             G5lnAdu3cbWCHaBuCMuYM///urB+GMWSLad1D8eUL6ampqVzDbeEH6t5E8iVMMCNKMbGxq58Fppo
87             Aqh2EKx6FP/Ub//4k+vr6///nP/bdf/kf//viba2tv//////mQAAAAAAAAAAAAAAAAAAAAAAAAAA
88             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAC4ALAAAAAASABIAAAaRQJdw
89             SCwaj8ik0jUYTBidAEA5YFkplANhehxABGAwpKHYRByVwHBibbvbo8+Q0TrZ7/jWBTHEtP6AgX8G
90             K0MWLSWJiostEoVCBy0qk5SVLQmPLh4tKZ2eny0LmQ0tKKanqC0hmQotJK+wsS0PfEIBZxUgHCIa
91             BhIJCw8ZBUMABAUrycrLBQREAAEm0tPUUktKQQA7
92             ',
93             'folderopen.gif' =>
94             'R0lGODlhEgASANUAAO/v76VzDfv7+8yZNMHBweTk5JpoAqBuCMuYM8mWMZ5sBpxqBPr7/Le3t///
95             pcaaGvDker2KJc+iJqd1D7B+GOKzQ8KPKqJwCrOBG7WCHbeEH9e4QNq/bP/rhJlnAffwiaampuLB
96             UMmgIf3VcKRyDP/XhLqHIqNxC8iVMMbGxqx6FP/kf//bdf/vievr67a2tv/4k8aaGf//nP//mf//
97             /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADUALAAAAAASABIAAAaVwJpw
98             SCwaj8ikUjgYIBIogEA5oFkZDEtheqzKvl9axKTJYCiAIYIGblutqtQwQYPZ73jZpCGM+f+AfiEd
99             Jy99M21tMxwxJQeGNTGIeHcyHzEjCpAAki2en54OIhULkAKSMiuqqysOGxIGkDWcMyy2t7YQDx58
100             QqcBwMAkFwcKCwYgBEQFBC/Oz9AEBUUALtbX2FJLSUEAOw==
101             ',
102             'globe.gif' =>
103             'R0lGODlhEwASAPcAAPr7/AFyAQFCpwGD6jy3/wE9on7N0AE+pAFjyMLI0AE2mwF94wGP9QFpzgU3
104             nISSopWgrmJsfTNLfgFHqAFuBilNiTp4sLnGzwWb/0xYb/P09mRygGl0hRlnMgR12V2Pr6e4xF9p
105             eS2Cyh5FpBdSfgF84YmisdPa30hjvw+foQFYvlWj4HWIlkWb5gk5n/b4+gw+kgFMscXb6ylmieDj
106             5ju2pylTsniElgqd/u/x8wGW/O7v8SVMsUq+JSSJXQFiwfv+/AFqvB9ntobZeKbc/9vt+B+YmW2r
107             vKruzQGPkm3PPrjmxQFIklrFLVbD4QGMYaXkoIPD13LC+nGw5AGFQHG66gF2eBaJxket9sLf84HI
108             +wF7axBdbg2c0CR+1QFsEIfJ7yqoUIbH41tldgF+KzVTjn3QfitZgTJZkaDR8gKDsXeWrE+zogE3
109             nCeKzQFtJ0tknjdnbQGB6EJgxQFqAcLJ0WC//yKm/wE+o7vI0ARozEOz/4/g/4KToyaX4/D09pCp
110             uNHV24HA6gw7oAF/AXWKnEVSb5TI6VzDTrPprxBQts7e6FNdcBA9oySd9RRjPAhnD2NvgIydrF+6
111             wdLo9v7//2K+twKSdDmKyeD56wGCyHq12VnF+ZXXsARdTjZWthShoo7gtilDlAFw1RCXvF+z6p/R
112             8kqZzAF0Oj5jjFuJqgFoAkRgxtzr9YmcrJKsugFlylfBgxJGhjJIeFnFuhmi/+bo65ipt8Hn+UhV
113             co7B5SZowAGBKoaZqAGGAVHBUwF8Qq7Y819qe4DEoVyYwrnb8QGN9GCy6QFTuHB9jgGY/gFRtuTu
114             9ZOhr150iwFbwTFiwFus4h9mYt/y+kWZ35vM7hGfccz43Xy/6m3BuS1GiYveqDRfwnbUV4rdu///
115             /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
116             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAN8ALAAAAAATABIA
117             AAj/AL8JHEiwVTVspar8ITiwiJhswyaBibJJUq9Trxh+S2OAVihvSzqRcoTpmy5ADIPFqrHtGpBE
118             TbrIuXJEBgiGbHoogTItExJOoAbw8rHmAkFTC8KYwTWkGx8COp4AozAjD8Epo4wQQfTLCQEcxqig
119             oiONBUFqerRYspYCgzIGmgi98cRlA8EVLaR4UJPk0oASVgKs6kAiBMFDdrzAarDFF5kgCJA9ilNB
120             GMFjWAQse/YjwBcVMfCcgTMr2UBKe0QIaHNgAiQmBRS4+CSKEYSBWe44E6JoEAxZDhrxmDPCEAca
121             A4vVinTCwi5uKFhBs6EtQ4QEOQYy8+NGUDRiqdCUJJGQa8yNQDsADHyxSNUHE4Vc3erzoFkdWxoA
122             VNLIv7///98EBAA7
123             ',
124             'join.gif' =>
125             'R0lGODlhEgASAIABAICAgP///yH5BAEAAAEALAAAAAASABIAAAIcjB+Ay+2rnpwo0uss3kf5BGoc
126             NJZiSZ2opK5BAQA7
127             ',
128             'joinbottom.gif' =>
129             'R0lGODlhEgASAIABAICAgP///yH5BAEAAAEALAAAAAASABIAAAIZjB+Ay+2rnpwo0uss3kf5BGrc
130             SJbmiaZGAQA7
131             ',
132             'line.gif' =>
133             'R0lGODlhEgASAIABAICAgP///yH5BAEAAAEALAAAAAASABIAAAIZjB+Ay+2rnpwo0uss3kfz7X1X
134             KE5k+ZxoAQA7
135             ',
136             'minus.gif' =>
137             'R0lGODlhEgASAJEDAIKCgoCAgAAAAP///yH5BAEAAAMALAAAAAASABIAAAInnD+By+2rnpyhWvsi
138             zE0zf4CIIpRlgiqaiDosa7zZdU22A9y6u98FADs=
139             ',
140             'minusbottom.gif' =>
141             'R0lGODlhEgASAJECAICAgAAAAP///wAAACH5BAEAAAIALAAAAAASABIAAAImlC+Ay+2rnpygWvsi
142             zE0zf4CIEpRlgiqaiDosa7zZdU32jed6XgAAOw==
143             ',
144             'nolines_minus.gif' =>
145             'R0lGODlhEgASAPcDAIKCgoCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
146             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
147             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
148             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
149             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
150             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
151             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
152             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
153             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
154             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
155             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
156             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
157             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
158             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAMALAAAAAASABIA
159             AAg6AAcIHEiwoMGDCBMqXJgwgMOHDxseDCDRIEWEFwtmtDjgn0ePAzZqnFhxJEaSGCFCZMiypcuX
160             MBMGBAA7
161             ',
162             'nolines_plus.gif' =>
163             'R0lGODlhEgASAPcDAIKCgoCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
164             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
165             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
166             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
167             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
168             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
169             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
170             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
171             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
172             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
173             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
174             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
175             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
176             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAMALAAAAAASABIA
177             AAhDAAcIHEiwoMGDCBMqXJgwgMOHDxseDCBR4L+BFBFmHHBR4EaDFP+JFDngY8GNHUtW5IhxJUGT
178             LyFCZEizps2bOBMGBAA7
179             ',
180             'openbook.gif' =>
181             'R0lGODlhFQASAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD/
182             /////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
183             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBm
184             AABmMwBmZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/
185             MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNm
186             ZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/
187             mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZm
188             zGZm/2aZAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb/
189             /5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZ
190             AJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwA
191             M8wAZswAmcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZ
192             ZsyZmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8A
193             mf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+Z
194             zP+Z///MAP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP///ywAAAAAFQASAAAInAAfCBxI
195             sKDBgqMOKiSICpaohQoBzHkwrRDBP6hQLQRgSaDGB6gePvizUY5AaqJIClwwCgCAgwAuDQQw7cEC
196             jw8uvSwocaazgQtIztlJMOZMWDYFWhxqkONMakAJPWDK06RAmkkfJLREdKaliQ8A/BQoqqacrjPn
197             yMQ6itBYrhFNAijkp+ZAqjDnyLn0da/asxBdCh7sEqLhw4cDAgA7
198             ',
199             'page.gif' =>
200             'R0lGODlhEgASAOYAAPv7++/v7/j7/+32/8HBweTk5P39/djr/8Df//7///P5/8Ph//T09fn5+YGV
201             w2t0pc7n/15hkFWn7ZOq0nqDsMDA/9nh7YSbyoqo2eTx/5G46pK873N+sPX6//f395Cjy83m/7rd
202             /9jl9m13qGVqmoeh0n+OvI+z5Yyu387T//b6/2dtnvz9/32JtpS/8sbGxv7+/tvn92lwom96rHJ8
203             rnSAsoep3NHp/8nk/7e3t+vr67a2tun1/3V4o+Hw/9vt/////wAAAAAAAAAAAAAAAAAAAAAAAAAA
204             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
205             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
206             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5
207             BAEAAEEALAAAAAASABIAAAejgEGCg4SFhoeILjaLjDY1AQCHG0AGAA0eDBY1E5CGGjBAoQkCMTUS
208             HwGGJwaiAh0iNbEvhiihAgIDPDwpFRw5hhgsuLk8Pz8HNL+FJSoKuT4+xzczyoQXzjzQxjcgI9WD
209             DrraPzc4OA/fgibZ0eTmCzLpQS0Z7TflCwgr8hT2EOYIQpCQ16OgwYMRCBgqQGCHw4cOCRQwBCCA
210             josYL3ZCxNFQIAA7
211             ',
212             'plus.gif' =>
213             'R0lGODlhEgASAJECAICAgAAAAP///wAAACH5BAEAAAIALAAAAAASABIAAAIqlC+Ay+2rnpygWvsi
214             zCcczWieAW7BeSaqookfZ4yqU5LZdU06vfe8rysAADs=
215             ',
216             'plusbottom.gif' =>
217             'R0lGODlhEgASAJECAICAgAAAAP///wAAACH5BAEAAAIALAAAAAASABIAAAIplC+Ay+2rnpygWvsi
218             zCcczWieAW7BeSaqookfZ4yqU5LZdU36zvd+XwAAOw==
219             ',
220             'question.gif' =>
221             'R0lGODlhEgASAPelAOP0//7//9bs//n///j//9Ls/8Pn//r//6rB1t3f5crO2N7g5k1livT4+7PW
222             9dXt/+v4/+Xl5LHW9Ov6/+j1/6CyxrfCz9rd5Nzj6un1/Z6ouwcvj8HBzO7+/+3//+Ln7BUuXNHv
223             /6K4y+/9/wEBZvX08snn/19qhufs8fP7/87n/+/t7czr/5q1yk55q97v/3Cfztnu//z//+X6/ypI
224             dMHY7rPc/7fX9cbl/9/h52WHr2yKrd/0/9fw/4KTs9rm75Svzb2+ya690pu92mWJrcT3//H//+Dv
225             /Xym35S216Ouwsvt/3N/mMnZ5gEBcMnq/wEBXs/o/wEBetzw/zdYpTdZpsvP2ClGml2N3b3H0Nzu
226             /2Z2lF1ricrl/93w/97h6JqluktojM/u/+/z9g8pVff4+ebu9q+1xa6/zzdFaIiXr5Wyz0xslrTK
227             4uL//2uIp11rh8Xj/NXn+Oz2/9bf6bG2xAEBePP//1xwkK/K5Nbr/8fp/2OBtG53kai3ykVCYwEB
228             de/6/7O4xabI+fD//+by/x8+jDhZpM/q/6jK58nO19ny/7jV7ZO42NHr/9H4/2ZwimSV6VBxwMDX
229             7Nvf5hYwX5m20sfb6Ieqyk9Yjr/k/cPM2NDp/+/098Tl9yQ9jLfW+Mne8sjU30JklP///wAAAAAA
230             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
231             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
232             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
233             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
234             AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAKUALAAAAAASABIA
235             AAjxAEsJHEiwoMEyGMaQWthg0xeDAlGUWKjoz5mFAegY/LBiIalMUK54JCWEoJkIpA6kSDmoAykK
236             gRaqGSiq04A5A5r4AKOEAAAtE2S0USAwSwYIhUb8METiUwAvemLMCMVEoIUjAF5MIYXAThUCDzgV
237             WDQJjkA0cngIEHAHCCAqRqJ0QeQoDxeBFS71KKDCwxonhwiZwPEkzo4+AimJqBFCjBs+UjZ4WmLg
238             xhAQVgb6acGIBShJkbAgMSAhCQ1IBTW8sZRI055HDhoRqXQCYo4tDMJgsqGDTJo6EAlyYFNkVJDg
239             BgXBcJEAucEFeC44n04wIAA7
240             ',
241             );
242              
243             =pod
244              
245             =begin classdoc
246              
247             Return the dtree Javascript.
248              
249             @return the dtree Javascript as a string.
250              
251             =end classdoc
252              
253             =cut
254              
255             sub getJavascript {
256 2     2 0 13 return <<'EOJS';
257             /*--------------------------------------------------|
258             | dTree 2.05| www.destroydrop.com/javascripts/tree/ |
259             |---------------------------------------------------|
260             | Copyright (c) 2002-2003 Geir Landrö |
261             | |
262             | This script can be used freely as long as all |
263             | copyright messages are intact. |
264             | |
265             | Updated: 17.04.2003 |
266             |--------------------------------------------------*/
267             /*
268             * Add'l update 2007-08-14 D. Arnold:
269             * Added imgPath parameter to constructor
270             * Added addWithIcons method
271             * Added closeIcon, openIcon default config icons
272             */
273             // Node object
274             function Node(id, pid, name, url, title, target, icon, iconOpen, open) {
275             this.id = id;
276             this.pid = pid;
277             this.name = name;
278             this.url = url;
279             this.title = title;
280             this.target = target;
281             this.icon = icon;
282             this.iconOpen = iconOpen;
283             this._io = open || false;
284             this._is = false;
285             this._ls = false;
286             this._hc = false;
287             this._ai = 0;
288             this._p;
289             };
290              
291             // Tree object
292             function dTree(objName, imgPath) {
293             this.config = {
294             target : null,
295             folderLinks : true,
296             useSelection : true,
297             useCookies : true,
298             useLines : true,
299             useIcons : true,
300             useStatusText : false,
301             closeSameLevel : false,
302             inOrder : false,
303             closeIcon : imgPath + '/folder.gif',
304             openIcon : imgPath + '/folderopen.gif'
305             }
306             this.icon = {
307             root : imgPath + '/base.gif',
308             folder : imgPath + '/folder.gif',
309             folderOpen : imgPath + '/folderopen.gif',
310             node : imgPath + '/page.gif',
311             empty : imgPath + '/empty.gif',
312             line : imgPath + '/line.gif',
313             join : imgPath + '/join.gif',
314             joinBottom : imgPath + '/joinbottom.gif',
315             plus : imgPath + '/plus.gif',
316             plusBottom : imgPath + '/plusbottom.gif',
317             minus : imgPath + '/minus.gif',
318             minusBottom : imgPath + '/minusbottom.gif',
319             nlPlus : imgPath + '/nolines_plus.gif',
320             nlMinus : imgPath + '/nolines_minus.gif'
321             };
322             this.obj = objName;
323             this.aNodes = [];
324             this.aIndent = [];
325             this.root = new Node(-1);
326             this.selectedNode = null;
327             this.selectedFound = false;
328             this.completed = false;
329             };
330              
331             // Adds a new node to the node array
332             dTree.prototype.add = function(id, pid, name, url, title, target, icon, iconOpen, open) {
333             this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, title, target, icon, iconOpen, open);
334             };
335              
336             // Adds a new node to the node array using default open/close icons
337             dTree.prototype.addWithIcons = function(id, pid, name, url, title, target, open) {
338             this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, title, target, this.config.closeIcon, this.config.openIcon, open);
339             };
340              
341             // Open/close all nodes
342             dTree.prototype.openAll = function() {
343             this.oAll(true);
344             };
345             dTree.prototype.closeAll = function() {
346             this.oAll(false);
347             };
348              
349             // Outputs the tree to the page
350             dTree.prototype.toString = function() {
351             var str = '
\n';
352             if (document.getElementById) {
353             if (this.config.useCookies) this.selectedNode = this.getSelected();
354             str += this.addNode(this.root);
355             } else str += 'Browser not supported.';
356             str += '';
357             if (!this.selectedFound) this.selectedNode = null;
358             this.completed = true;
359             return str;
360             };
361              
362             // Creates the tree structure
363             dTree.prototype.addNode = function(pNode) {
364             var str = '';
365             var n=0;
366             if (this.config.inOrder) n = pNode._ai;
367             for (n; n
368             if (this.aNodes[n].pid == pNode.id) {
369             var cn = this.aNodes[n];
370             cn._p = pNode;
371             cn._ai = n;
372             this.setCS(cn);
373             if (!cn.target && this.config.target) cn.target = this.config.target;
374             if (cn._hc && !cn._io && this.config.useCookies) cn._io = this.isOpen(cn.id);
375             if (!this.config.folderLinks && cn._hc) cn.url = null;
376             if (this.config.useSelection && cn.id == this.selectedNode && !this.selectedFound) {
377             cn._is = true;
378             this.selectedNode = n;
379             this.selectedFound = true;
380             }
381             str += this.node(cn, n);
382             if (cn._ls) break;
383             }
384             }
385             return str;
386             };
387              
388             // Creates the node icon, url and text
389             dTree.prototype.node = function(node, nodeId) {
390             var str = '
' + this.indent(node, nodeId);
391             if (this.config.useIcons) {
392             if (!node.icon) node.icon = (this.root.id == node.pid) ? this.icon.root : ((node._hc) ? this.icon.folder : this.icon.node);
393             if (!node.iconOpen) node.iconOpen = (node._hc) ? this.icon.folderOpen : this.icon.node;
394             if (this.root.id == node.pid) {
395             node.icon = this.icon.root;
396             node.iconOpen = this.icon.root;
397             }
398             str += '';
399             }
400             if (node.url) {
401             str += '
402             if (node.title) str += ' title="' + node.title + '"';
403             if (node.target) str += ' target="' + node.target + '"';
404             if (this.config.useStatusText) str += ' onmouseover="window.status=\'' + node.name + '\';return true;" onmouseout="window.status=\'\';return true;" ';
405             if (this.config.useSelection && ((node._hc && this.config.folderLinks) || !node._hc))
406             str += ' onclick="javascript: ' + this.obj + '.s(' + nodeId + ');"';
407             str += '>';
408             }
409             else if ((!this.config.folderLinks || !node.url) && node._hc && node.pid != this.root.id)
410             str += '';
411             str += node.name;
412             if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += '';
413             str += '';
414             if (node._hc) {
415             str += '
';
416             str += this.addNode(node);
417             str += '';
418             }
419             this.aIndent.pop();
420             return str;
421             };
422              
423             // Adds the empty and line icons
424             dTree.prototype.indent = function(node, nodeId) {
425             var str = '';
426             if (this.root.id != node.pid) {
427             for (var n=0; n
428             str += '';
429             (node._ls) ? this.aIndent.push(0) : this.aIndent.push(1);
430             if (node._hc) {
431             str += ' 432             if (!this.config.useLines) str += (node._io) ? this.icon.nlMinus : this.icon.nlPlus;
433             else str += ( (node._io) ? ((node._ls && this.config.useLines) ? this.icon.minusBottom : this.icon.minus) : ((node._ls && this.config.useLines) ? this.icon.plusBottom : this.icon.plus ) );
434             str += '" alt="" />';
435             } else str += '';
436             }
437             return str;
438             };
439              
440             // Checks if a node has any children and if it is the last sibling
441             dTree.prototype.setCS = function(node) {
442             var lastId;
443             for (var n=0; n
444             if (this.aNodes[n].pid == node.id) node._hc = true;
445             if (this.aNodes[n].pid == node.pid) lastId = this.aNodes[n].id;
446             }
447             if (lastId==node.id) node._ls = true;
448             };
449              
450             // Returns the selected node
451             dTree.prototype.getSelected = function() {
452             var sn = this.getCookie('cs' + this.obj);
453             return (sn) ? sn : null;
454             };
455              
456             // Highlights the selected node
457             dTree.prototype.s = function(id) {
458             if (!this.config.useSelection) return;
459             var cn = this.aNodes[id];
460             if (cn._hc && !this.config.folderLinks) return;
461             if (this.selectedNode != id) {
462             if (this.selectedNode || this.selectedNode==0) {
463             eOld = document.getElementById("s" + this.obj + this.selectedNode);
464             eOld.className = "node";
465             }
466             eNew = document.getElementById("s" + this.obj + id);
467             eNew.className = "nodeSel";
468             this.selectedNode = id;
469             if (this.config.useCookies) this.setCookie('cs' + this.obj, cn.id);
470             }
471             };
472              
473             // Toggle Open or close
474             dTree.prototype.o = function(id) {
475             var cn = this.aNodes[id];
476             this.nodeStatus(!cn._io, id, cn._ls);
477             cn._io = !cn._io;
478             if (this.config.closeSameLevel) this.closeLevel(cn);
479             if (this.config.useCookies) this.updateCookie();
480             };
481              
482             // Open or close all nodes
483             dTree.prototype.oAll = function(status) {
484             for (var n=0; n
485             if (this.aNodes[n]._hc && this.aNodes[n].pid != this.root.id) {
486             this.nodeStatus(status, n, this.aNodes[n]._ls)
487             this.aNodes[n]._io = status;
488             }
489             }
490             if (this.config.useCookies) this.updateCookie();
491             };
492              
493             // Opens the tree to a specific node
494             dTree.prototype.openTo = function(nId, bSelect, bFirst) {
495             if (!bFirst) {
496             for (var n=0; n
497             if (this.aNodes[n].id == nId) {
498             nId=n;
499             break;
500             }
501             }
502             }
503             var cn=this.aNodes[nId];
504             if (cn.pid==this.root.id || !cn._p) return;
505             cn._io = true;
506             cn._is = bSelect;
507             if (this.completed && cn._hc) this.nodeStatus(true, cn._ai, cn._ls);
508             if (this.completed && bSelect) this.s(cn._ai);
509             else if (bSelect) this._sn=cn._ai;
510             this.openTo(cn._p._ai, false, true);
511             };
512              
513             // Closes all nodes on the same level as certain node
514             dTree.prototype.closeLevel = function(node) {
515             for (var n=0; n
516             if (this.aNodes[n].pid == node.pid && this.aNodes[n].id != node.id && this.aNodes[n]._hc) {
517             this.nodeStatus(false, n, this.aNodes[n]._ls);
518             this.aNodes[n]._io = false;
519             this.closeAllChildren(this.aNodes[n]);
520             }
521             }
522             }
523              
524             // Closes all children of a node
525             dTree.prototype.closeAllChildren = function(node) {
526             for (var n=0; n
527             if (this.aNodes[n].pid == node.id && this.aNodes[n]._hc) {
528             if (this.aNodes[n]._io) this.nodeStatus(false, n, this.aNodes[n]._ls);
529             this.aNodes[n]._io = false;
530             this.closeAllChildren(this.aNodes[n]);
531             }
532             }
533             }
534              
535             // Change the status of a node(open or closed)
536             dTree.prototype.nodeStatus = function(status, id, bottom) {
537             eDiv = document.getElementById('d' + this.obj + id);
538             eJoin = document.getElementById('j' + this.obj + id);
539             if (this.config.useIcons) {
540             eIcon = document.getElementById('i' + this.obj + id);
541             eIcon.src = (status) ? this.aNodes[id].iconOpen : this.aNodes[id].icon;
542             }
543             eJoin.src = (this.config.useLines)?
544             ((status)?((bottom)?this.icon.minusBottom:this.icon.minus):((bottom)?this.icon.plusBottom:this.icon.plus)):
545             ((status)?this.icon.nlMinus:this.icon.nlPlus);
546             eDiv.style.display = (status) ? 'block': 'none';
547             };
548              
549              
550             // [Cookie] Clears a cookie
551             dTree.prototype.clearCookie = function() {
552             var now = new Date();
553             var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
554             this.setCookie('co'+this.obj, 'cookieValue', yesterday);
555             this.setCookie('cs'+this.obj, 'cookieValue', yesterday);
556             };
557              
558             // [Cookie] Sets value in a cookie
559             dTree.prototype.setCookie = function(cookieName, cookieValue, expires, path, domain, secure) {
560             document.cookie =
561             escape(cookieName) + '=' + escape(cookieValue)
562             + (expires ? '; expires=' + expires.toGMTString() : '')
563             + (path ? '; path=' + path : '')
564             + (domain ? '; domain=' + domain : '')
565             + (secure ? '; secure' : '');
566             };
567              
568             // [Cookie] Gets a value from a cookie
569             dTree.prototype.getCookie = function(cookieName) {
570             var cookieValue = '';
571             var posName = document.cookie.indexOf(escape(cookieName) + '=');
572             if (posName != -1) {
573             var posValue = posName + (escape(cookieName) + '=').length;
574             var endPos = document.cookie.indexOf(';', posValue);
575             if (endPos != -1) cookieValue = unescape(document.cookie.substring(posValue, endPos));
576             else cookieValue = unescape(document.cookie.substring(posValue));
577             }
578             return (cookieValue);
579             };
580              
581             // [Cookie] Returns ids of open nodes as a string
582             dTree.prototype.updateCookie = function() {
583             var str = '';
584             for (var n=0; n
585             if (this.aNodes[n]._io && this.aNodes[n].pid != this.root.id) {
586             if (str) str += '.';
587             str += this.aNodes[n].id;
588             }
589             }
590             this.setCookie('co' + this.obj, str);
591             };
592              
593             // [Cookie] Checks if a node id is in a cookie
594             dTree.prototype.isOpen = function(id) {
595             var aOpen = this.getCookie('co' + this.obj).split('.');
596             for (var n=0; n
597             if (aOpen[n] == id) return true;
598             return false;
599             };
600              
601             // If Push and pop is not implemented by the browser
602             if (!Array.prototype.push) {
603             Array.prototype.push = function array_push() {
604             for(var i=0;i
605             this[this.length]=arguments[i];
606             return this.length;
607             }
608             };
609             if (!Array.prototype.pop) {
610             Array.prototype.pop = function array_pop() {
611             lastElement = this[this.length-1];
612             this.length = Math.max(this.length-1,0);
613             return lastElement;
614             }
615             };
616             EOJS
617             }
618              
619             =pod
620              
621             =begin classdoc
622              
623             Return the dtree CSS stylesheet.
624              
625             @return the dtree CSS stylesheet as a string.
626              
627             =end classdoc
628              
629             =cut
630              
631             sub getCSS {
632 2     2 0 19 return <<'EOCSS';
633             /*--------------------------------------------------|
634             | dTree 2.05 | www.destroydrop.com/javascript/tree/ |
635             |---------------------------------------------------|
636             | Copyright (c) 2002-2003 Geir Landrö |
637             |--------------------------------------------------*/
638              
639             .dtree {
640             font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
641             font-size: 11px;
642             color: #666;
643             white-space: nowrap;
644             }
645             .dtree img {
646             border: 0px;
647             vertical-align: middle;
648             }
649             .dtree a {
650             color: #333;
651             text-decoration: none;
652             }
653             .dtree a.node, .dtree a.nodeSel {
654             white-space: nowrap;
655             padding: 1px 2px 1px 2px;
656             }
657             .dtree a.node:hover, .dtree a.nodeSel:hover {
658             color: #333;
659             text-decoration: underline;
660             }
661             .dtree a.nodeSel {
662             background-color: #c0d2ec;
663             }
664             .dtree .clip {
665             overflow: hidden;
666             }
667              
668             .dtree a.rootnode {
669             white-space: nowrap;
670             padding: 1px 2px 1px 2px;
671             color: #000;
672             font-weight: bold;
673             }
674             EOCSS
675             }
676              
677             =pod
678              
679             =begin classdoc
680              
681             Return the specified dtree icon image data.
682              
683             @return the dtree icon image data.
684              
685             =end classdoc
686              
687             =cut
688              
689             sub getIcon {
690 2     2 0 5 my ($self, $image) = @_;
691 2   33     7 $image ||= $self; # if called as expoerted method
692 2         25 return decode_base64($dtree_images{$image});
693             }
694              
695             =pod
696              
697             =begin classdoc
698              
699             Return the dtree icon images.
700              
701             @returnlist the dtree icon images as a hash mapping icon file names to the image data
702              
703             =end classdoc
704              
705             =cut
706              
707             sub getIcons {
708 2     2 0 5 my %icons = ();
709 2         3 my ($k, $v);
710 2         170 $icons{$k} = decode_base64($v)
711             while (($k, $v) = each %dtree_images);
712 2         50 return %icons;
713             }
714              
715              
716             =pod
717              
718             =begin classdoc
719              
720             @constructor
721              
722             Create a new dtree widget object.
723              
724             @return the created widget object.
725              
726             =end classdoc
727              
728             =cut
729              
730 52     52 0 175 sub new { return bless {}, $_[0]; }
731              
732             =pod
733              
734             =begin classdoc
735              
736             Start the widget rendering.
737              
738             @param RootText text for root node of tree
739             @optional CSSPath full path to the stylesheet; default './css/dtree.css'
740             @optional JSPath full path to the Javascript document; default './js/dtree.js'
741             @optional UseIcons if true, widget includes open/close icons; default false
742             @optional RootIcon icon used for root node of tree; default none
743             @optional RootLink URL of root node of tree; default none
744             @optional Target name of target frem for tree links; default 'mainframe'
745             @optional CloseIcon icon used for closed nodes; default /folder.gif
746             @optional OpenIcon icon used for open node; default /folderopen.gif
747             @optional IconPath path to the icon image directory
748              
749             @return this widget object
750              
751             =end classdoc
752              
753             =cut
754              
755             sub start {
756 3     3 0 4 my $self = shift;
757 3         19 my %args = @_;
758 3   50     8 $args{IconPath} ||= './img';
759 3   50     7 $args{CSSPath} ||= './css/dtree.css';
760 3   50     6 $args{JSPath} ||= './js/dtree.js';
761 3 50       10 $args{Target} = $args{Target} ? "'$args{Target}'" : "'mainframe'";
762 3 50       9 $args{RootLink} = $args{RootLink} ? "'$args{RootLink}'" : 'null';
763 3 100       10 $args{RootIcon} = $args{RootIcon} ? "'$args{RootIcon}'" : 'null';
764 3 100       9 $args{OpenIcon} = $args{OpenIcon} ? "'$args{OpenIcon}'" : "'$args{IconPath}/folderopen.gif'";
765 3 100       11 $args{CloseIcon} = $args{CloseIcon} ? "'$args{CloseIcon}'" : "'$args{IconPath}/folder.gif'";
766 3   50     11 $args{RootText} ||= '';
767 3         25 $self->{_jstree} = "
768            
769            
770            
771            
772              
773            
774            
775            
776              
777            
869              
870            
871            

872             $adds
873            
874            
875             ";
876             }
877              
878             1;