v4 style
[freeside.git] / httemplate / elements / select-part_pkg.html
1 <%doc>
2
3 Example:
4
5   include( '/elements/select-part_pkg.html',
6
7     #strongly recommended (you want your forms to be "sticky" on errors, right?)
8     'curr_value' => 'current_value',
9   
10     #opt
11     'part_pkg'   => \@records,
12     'showdisabled' => 1, #defaults to 0, shows disabled if true
13     'toggle_disabled' => 1, #adds js to toggle display of disabled
14                             #currently cannot be used with many other options
15                             #currently must be used with multiple or disable_empty
16
17     #select-table.html options
18   )
19
20 </%doc>
21
22 <& /elements/select-table.html,
23      'table'          => 'part_pkg',
24      'agent_virt'     => 1,
25      'agent_null'     => 1,
26      'name_col'       => 'pkg',
27      'empty_label'    => 'Select package', #should this be the default?
28      'label_callback' => $opt{'label_callback'} || sub { shift->pkg_comment_only },
29      'hashref'        => \%hash,
30      %opt,
31 &>
32
33 % if ($opt{'toggle_disabled'}) {
34 %   unless ($toggle_disabled_init) {
35 %     $toggle_disabled_init = 1;
36
37 <% include('/elements/xmlhttp.html',
38         'url'  => $fsurl.'misc/xmlhttp-part_pkg.cgi',
39         'subs' => [ 'load_part_pkg' ],
40    ) %>
41
42 <SCRIPT>
43 var toggle_disabled_part_pkg_list = undefined;
44 function toggle_disabled_part_pkg (id,showdisabled,noload) {
45   // remove link text, only put it back if this works
46   var trigger = document.getElementById(id+'_switch');
47   trigger.innerHTML = '';
48   // if needed, load pkg_list before trying again
49   var pkg_list = toggle_disabled_part_pkg_list;
50   if (!pkg_list && !noload) {
51     load_part_pkg(
52       function (result) {
53         result = JSON.parse(result);
54         if (result) {
55           toggle_disabled_part_pkg_list = result;
56           toggle_disabled_part_pkg(id,showdisabled,true);
57         } else {
58           console.log('Error loading pkg list');
59         }
60       }
61     );
62     return;
63   }
64   if (!(pkg_list && pkg_list.length)) {
65     console.log('Cannot load pkg list, or pkg list empty');
66     return;
67   }
68   // remove all existing options, tracking which are selected
69   var selectbox = document.getElementById(id);
70   var selected = {};
71   for (var i = selectbox.length - 1; i >= 0; i--) {
72     var nextopt = selectbox.options[i];
73     selected[nextopt.value] = nextopt.selected;
74     nextopt.parentNode.removeChild(nextopt);
75   }
76   // regenerate options list from pkg list
77   for (var i = 0; i < pkg_list.length; i++) {
78     var pkginfo = pkg_list[i];
79     if (showdisabled || selected[pkginfo.pkgpart] || !pkginfo.disabled) {
80       var newopt = document.createElement('option');
81       newopt.value = pkginfo.pkgpart;
82       newopt.text = pkginfo.label;
83       newopt.selected = selected[newopt.value] ? true : false;
84       selectbox.appendChild(newopt);
85     }
86   }
87   trigger.innerHTML = showdisabled ? '<% $hidetext %>' : '<% $showtext %>';
88   trigger.onclick = function () { toggle_disabled_part_pkg(id,(showdisabled ? 0 : 1)) };
89 }
90 </SCRIPT>
91
92 %   } # unless $toggle_disabled_init
93
94 <BR><A 
95   HREF="javascript:void(0)"
96   STYLE="font-size: smaller"
97   ONCLICK="toggle_disabled_part_pkg('<% $opt{'id'} %>',<% $showdisabled ? '0' : '1' %>)"
98   ID="<% $opt{'id'} %>_switch"><% $showdisabled ? $hidetext : $showtext %></A>
99
100 % } # if $opt{'toggle_disabled'}
101
102 <%shared>
103 my $toggle_disabled_init = 0;
104 </%shared>
105 <%init>
106  
107 my( %opt ) = @_;
108
109 # toggle_disabled relies on matching search/label options with xmlhttp-part_pkg
110 # it would be difficult to handle these in the current xmlhttp implementation
111 # this is defensive coding, not a guarantee it'll work with options not listed here
112 if ($opt{'toggle_disabled'}) {
113   foreach my $someopt ( qw(
114     records
115     part_pkg
116     table
117     agent_virt
118     agent_null
119     agent_null_right
120     name_col
121     label_callback
122     hashref
123     extra_sql
124     addl_from
125     order_by
126     pre_options
127     post_options
128     select
129   ) ) {
130     die "Cannot use toggle_disabled with $someopt"
131       if exists $opt{$someopt};
132   }
133 }
134
135 # this would be fairly easy to implement, but not needed right now
136 die 'Use of toggle_disabled without multiple or disable_empty has not been implemented'
137   if $opt{'toggle_disabled'} && !($opt{'multiple'} || $opt{'disable_empty'});
138
139 $opt{'records'} = delete $opt{'part_pkg'}
140   if $opt{'part_pkg'};
141
142 my $showdisabled = $opt{'showdisabled'};
143
144 my %hash = ();
145 $hash{'disabled'} = '' unless $showdisabled;
146
147 if ( exists($opt{'classnum'}) && defined($opt{'classnum'}) ) {
148   if ( $opt{'classnum'} > 0 ) {
149     $hash{'classnum'} = $opt{'classnum'};
150   } elsif ( $opt{'classnum'} eq '' || $opt{'classnum'} == 0 ) {
151     $hash{'classnum'} = '';
152   } #else -1 or not specified, all classes, so don't set classnum
153 }
154
155 # currently can't handle this, either
156 die 'Use of toggle_disabled with classnum has not been implemented'
157   if $opt{'toggle_disabled'} && exists($hash{'classnum'});
158
159 # CAUTION: For proper functioning of toggle_disabled,
160 # please ensure changes to default options are synced with misc/xmlhttp-part_pkg.cgi
161
162 $opt{'select'} = 'part_pkg.*, setup_option.optionvalue AS _setup_fee,
163                               recur_option.optionvalue AS _recur_fee'
164   unless $opt{'select'};
165 $opt{'addl_from'} .= FS::part_pkg->join_options_sql;
166
167 $opt{'extra_sql'} .= ( keys(%hash) ? ' AND ' : ' WHERE ' ).
168                      FS::part_pkg->curuser_pkgs_sql;
169
170 my $showtext = emt("show disabled packages");
171 my $hidetext = emt("hide disabled packages");
172
173 </%init>