1 package SL::Presenter::Chart;
7 use Exporter qw(import);
8 our @EXPORT_OK = qw(chart_picker chart);
12 use SL::Presenter::EscapedText qw(escape is_escaped);
13 use SL::Presenter::Tag qw(input_tag name_to_id html_tag link_tag);
16 my ($chart, %params) = @_;
18 $params{display} ||= 'inline';
20 croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/;
22 my $text = escape($chart->accno);
23 if (! delete $params{no_link}) {
24 my $href = 'am.pl?action=edit_account&id=' . escape($chart->id);
25 $text = link_tag($href, $text, %params);
31 my ($name, $value, %params) = @_;
32 $value = SL::DB::Manager::Chart->find_by(id => $value) if $value && !ref $value;
33 my $id = delete($params{id}) || name_to_id($name);
34 my $fat_set_item = delete $params{fat_set_item};
36 my @classes = $params{class} ? ($params{class}) : ();
37 push @classes, 'chart_autocomplete';
38 push @classes, 'chartpicker_fat_set_item' if $fat_set_item;
40 # If there is no 'onClick' parameter, set it to 'this.select()',
41 # so that the user can type directly in the input field
42 # to search another chart.
43 if (!grep { m{onclick}i } keys %params) {
44 $params{onClick} = 'this.select()';
48 input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => "@classes", type => 'hidden', id => $id) .
49 join('', map { $params{$_} ? input_tag("", delete $params{$_}, id => "${id}_${_}", type => 'hidden') : '' } qw(type category choose booked status)) .
50 input_tag("", (ref $value && $value->can('displayable_name')) ? $value->displayable_name : '', id => "${id}_name", %params);
52 $::request->layout->add_javascripts('autocomplete_chart.js');
53 $::request->presenter->need_reinit_widgets($id);
55 html_tag('span', $ret, class => 'chart_picker');
58 sub picker { goto &chart_picker }
68 SL::Presenter::Chart - Chart related presenter stuff
72 # Create an html link for editing/opening a chart
73 my $object = SL::DB::Manager::Chart->get_first;
74 my $html = SL::Presenter::Chart::chart($object, display => 'inline');
76 see also L<SL::Presenter>
86 =item C<chart, $object, %params>
88 Returns a rendered version (actually an instance of
89 L<SL::Presenter::EscapedText>) of the chart object C<$object>
91 Remaining C<%params> are passed to the function
92 C<SL::Presenter::Tag::link_tag>. It can include:
98 Either C<inline> (the default) or C<table-cell>. Is passed to the function
99 C<SL::Presenter::Tag::link_tag>.
103 If falsish (the default) then the account number will be linked to the "edit"
112 =item C<chart_picker $name, $value, %params>
114 All-in-one picker widget for charts. The code was originally copied and adapted
115 from the part picker. The name will be both id and name of the resulting hidden
116 C<id> input field (but the ID can be overwritten with C<$params{id}>).
118 An additional dummy input will be generated which is used to find
119 chart. For a detailed description of its behaviour, see section
120 C<CHART PICKER SPECIFICATION>.
122 For some examples of usage see the test page at controller.pl?action=Chart/test_page
124 C<$value> can be a chart id or a C<Rose::DB:Object> instance.
126 C<%params> can include:
132 If C<%params> contains C<category> only charts of this category will be
133 available for selection (in the autocompletion and in the popup).
135 You may comma separate multiple categories, e.g C<A,Q,L>.
137 In SL::DB::Manager::Chart there is also a filter called C<selected_category>,
138 which filters the possible charts according to the category checkboxes the user
139 selects in the popup window. This filter may further restrict the results of
140 the filter category, but the user is not able to "break out of" the limits
141 defined by C<category>. In fact if the categories are restricted by C<category>
142 the popup template should only show checkboxes for those categories.
146 If C<%params> contains C<type> only charts of this type will be used for
147 autocompletion, i.e. the selection is filtered. You may comma separate multiple
150 Type is usually a filter for link: C<AR,AR_paid>
152 Type can also be a specially defined type: C<guv>, C<balance>, C<bank>
154 See the type filter in SL::DB::Manager::Chart.
158 If C<%params> is passed with choose=1 the input of the filter field in the
159 popup window is cleared. This is useful if a chart was already selected and we
160 want to choose a new chart and immediately see all options.
164 If C<%params> is passed with fat_set_item=1 the contents of the selected chart
165 object (the elements of the database chart table) are passed back via JSON into
166 the item object. There is an example on the test page.
168 Without fat_set_item only the variables id and name (displayable name) are
173 If C<%params> contains C<status> only charts of this status will be used
174 for autocompletion. C<status> can be one of the following strings:
175 C<valid>, C<invalid> or C<all>. C<valid> is the default if C<status> is
180 C<chart_picker> will register its javascript for inclusion in the next header
181 rendering. If you write a standard controller that only calls C<render> once, it
182 will just work. In case the header is generated in a different render call
183 (multiple blocks, ajax, old C<bin/mozilla> style controllers) you need to
184 include C<js/autocomplete_chart.js> yourself.
190 For users that don't regularly do bookkeeping and haven't memorised all the
191 account numbers and names there are some filter options inside the popup window
192 to quickly narrow down the possible matches. You can filter by
196 =item * chart accno or description, inside the input field
198 =item * accounts that have already been booked
200 =item * by category (AIELQC)
202 By selecting category checkboxes the list of available charts can be
203 restricted. If all checkboxes are unchecked all possible charts are shown.
207 There are two views in the list of accounts. By default all possible accounts are shown as a long list.
209 But you can also show more information, in this case the resulting list is automatically paginated:
213 =item * the balance of the account (as determined by SL::DB::Chart get_balance, which checks for user rights)
217 =item * the invoice date of the last transaction (may lie in the future)
221 The partpicker also has two views, but whereas the compact block view of the
222 partpicker allows part boxes to be aligned in two columns, the chartpicker
223 block view still only shows one chart per row, because there is more
224 information and the account names can be quite long. This behaviour is
225 determined by css, however, and could be changed (div.cpc_block). The downside
226 of this is that you have to scroll the window to reach the pagination controls.
228 The default view of the display logic is to use block view, so we don't have to
229 pass any parameters in the pagination GET. However, the default view for the
230 user is the list view, so the popup window is opened with the "Hide additional
231 information" select box already ticked.
233 =head1 CHART PICKER SPECIFICATION
235 The following list of design goals were applied:
241 Charts should not be perceived by the user as distinct inputs of chart number and
242 description but as a single object
246 Easy to use without documentation for novice users
250 Fast to use with keyboard for experienced users
254 Possible to use without any keyboard interaction for mouse (or touchscreen)
259 Must not leave the current page in event of ambiguity (cf. current select_item
264 Should not require a feedback/check loop in the common case
268 Should not be constrained to exact matches
272 The implementation consists of the following parts which will be referenced later:
278 A hidden input (id input), used to hold the id of the selected part. The only
279 input that gets submitted
283 An input (dummy input) containing a description of the currently selected chart,
284 also used by the user to search for charts
288 A jquery.autocomplete mechanism attached to the dummy field
292 A popup layer for both feedback and input of additional data in case of
297 An internal status of the chart picker, indicating whether id input and dummy
298 input are consistent. After leaving the dummy input the chart picker must
299 place itself in a consistent status.
303 A clickable icon (popup trigger) attached to the dummy input, which triggers the popup layer.
313 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
315 G. Richardson E<lt>information@kivitendo-premium.deE<gt>