Partpicker: filter.type nur mitschicken, wenn wirklich ein Typ angegeben war
[kivitendo-erp.git] / js / autocomplete_part.js
1 namespace('kivi', function(k){
2   k.PartPickerCache = { }
3   k.PartPicker = function($real, options) {
4     var o = $.extend({
5       limit: 20,
6       delay: 50,
7     }, options);
8     var STATES = {
9       UNIQUE: 1,
10       UNDEFINED: 0,
11     }
12     var real_id = $real.attr('id');
13     var $dummy  = $('#' + real_id + '_name');
14     var $type   = $('#' + real_id + '_type');
15     var $column = $('#' + real_id + '_column');
16     var state   = STATES.PICKED;
17     var last_real = $real.val();
18     var last_dummy = $dummy.val();
19     var open_dialog = function(){
20       open_jqm_window({
21         url: 'controller.pl?action=Part/part_picker_search',
22         data: $.extend({
23           real_id: real_id,
24         }, ajax_data($dummy.val())),
25         id: 'part_selection',
26       });
27       return true;
28     };
29
30     function ajax_data(term) {
31       var data = {
32         'filter.all:substr::ilike': term,
33         'filter.obsolete': 0,
34         column:   $column.val()===undefined ? '' : $column.val(),
35         current:  $real.val(),
36       };
37
38       var type = $type.val();
39       if (type !== '')
40         data['filter.type'] = type.split(',');
41
42       return data;
43     }
44
45     function set_item (item) {
46       if (item.id) {
47         $real.val(item.id);
48         // autocomplete ui has name, ajax items have description
49         $dummy.val(item.name ? item.name : item.description);
50       } else {
51         $real.val('');
52         $dummy.val('');
53       }
54       state = STATES.PICKED;
55       last_real = $real.val();
56       last_dummy = $dummy.val();
57       $real.trigger('change');
58     }
59
60     function make_defined_state () {
61       if (state == STATES.PICKED)
62         return true
63       else if (state == STATES.UNDEFINED && $dummy.val() == '')
64         set_item({})
65       else
66         set_item({ id: last_real, name: last_dummy })
67     }
68
69     function update_results () {
70       $.ajax({
71         url: 'controller.pl?action=Part/part_picker_result',
72         data: $.extend({
73             'real_id': $real.val(),
74         }, ajax_data(function(){ var val = $('#part_picker_filter').val(); return val === undefined ? '' : val })),
75         success: function(data){ $('#part_picker_result').html(data) }
76       });
77     };
78
79     function close_popup() {
80       $('#part_selection').jqmClose()
81     };
82
83     $dummy.autocomplete({
84       source: function(req, rsp) {
85         $.ajax($.extend(o, {
86           url:      'controller.pl?action=Part/ajax_autocomplete',
87           dataType: "json",
88           data:     ajax_data(req.term),
89           success:  function (data){ rsp(data) }
90         }));
91       },
92       select: function(event, ui) {
93         set_item(ui.item);
94       },
95     });
96     /*  In case users are impatient and want to skip ahead:
97      *  Capture <enter> key events and check if it's a unique hit.
98      *  If it is, go ahead and assume it was selected. If it wasn't don't do
99      *  anything so that autocompletion kicks in.  For <tab> don't prevent
100      *  propagation. It would be nice to catch it, but javascript is too stupid
101      *  to fire a tab event later on, so we'd have to reimplement the "find
102      *  next active element in tabindex order and focus it".
103      */
104     $dummy.keypress(function(event){
105       if (event.keyCode == 13 || event.keyCode == 9) { // enter or tab or tab
106         // if string is empty assume they want to delete
107         if ($dummy.val() == '') {
108           set_item({});
109           return true;
110         } else if (state == STATES.PICKED) {
111           return true;
112         }
113         $.ajax({
114           url: 'controller.pl?action=Part/ajax_autocomplete',
115           dataType: "json",
116           data: $.extend( ajax_data($dummy.val()), { prefer_exact: 1 } ),
117           success: function (data){
118             if (data.length == 1) {
119               set_item(data[0]);
120               if (event.keyCode == 13)
121                 $('#update_button').click();
122             } else if (data.length > 1) {
123              if (event.keyCode == 13)
124                 open_dialog();
125               else
126                 make_defined_state();
127             } else {
128               if (event.keyCode == 9)
129                 make_defined_state();
130             }
131           }
132         });
133         if (event.keyCode == 13)
134           return false;
135       } else {
136         state = STATES.UNDEFINED;
137       }
138     });
139
140 //    $dummy.blur(make_defined_state);  // blur triggers also on open_jqm_dialog
141
142     // now add a picker div after the original input
143     var pcont  = $('<span>').addClass('position-absolute');
144     var picker = $('<div>');
145     $dummy.after(pcont);
146     pcont.append(picker);
147     picker.addClass('icon16 CRM--Schnellsuche').click(open_dialog);
148
149     return {
150       real:           function() { return $real },
151       dummy:          function() { return $dummy },
152       type:           function() { return $type },
153       column:         function() { return $column },
154       update_results: update_results,
155       set_item:       set_item,
156       reset:          make_defined_state,
157       init_results:    function () {
158         $('div.part_picker_part').each(function(){
159           $(this).click(function(){
160             set_item({
161               name: $(this).children('input.part_picker_description').val(),
162               id:   $(this).children('input.part_picker_id').val(),
163             });
164             close_popup();
165             return true;
166           });
167         });
168         $('#part_selection').keypress(function(e){
169            if (e.keyCode == 27) { // escape
170              close_popup();
171              $dummy.focus();
172            }
173         });
174       }
175     }
176   }
177 });
178
179 $(function(){
180   $('input.part_autocomplete').each(function(i,real){
181     kivi.PartPickerCache[real.id] = new kivi.PartPicker($(real));
182   })
183 });