Bug 19103 - Stored XSS in patron-attr-types.pl
[koha.git] / koha-tmpl / intranet-tmpl / prog / js / additem.js
1 function addItem( node, unique_item_fields ) {
2     var index = $(node).closest("div").attr('id');
3     var current_qty = parseInt($("#quantity").val());
4     var max_qty;
5     if($("#quantity_to_receive").length != 0){
6         max_qty = parseInt($("#quantity_to_receive").val());
7     } else  {
8         max_qty = 99999;
9     }
10     if ( $("#items_list table").find('tr[idblock="' + index + '"]').length == 0 ) {
11         if ( current_qty < max_qty ) {
12             if ( current_qty < max_qty - 1 )
13                 cloneItemBlock(index, unique_item_fields);
14             addItemInList(index, unique_item_fields);
15             $("#" + index).find("input[name='buttonPlus']").val( (window.MSG_ADDITEM_JS_UPDATEITEM ) );
16             $("#"+ index).find("input[name='buttonPlusMulti']").remove();
17             $("#" + index).find("input[name='multiValue']").remove();
18             $("#quantity").val(current_qty + 1).change();
19         } else if ( current_qty >= max_qty ) {
20             alert(window.MSG_ADDITEM_JS_CANT_RECEIVE_MORE_ITEMS
21                 || "You can't receive any more items.");
22         }
23     } else {
24         if ( current_qty < max_qty )
25             cloneItemBlock(index, unique_item_fields);
26         var tr = constructTrNode(index);
27         $("#items_list table").find('tr[idblock="' + index + '"]:first').replaceWith(tr);
28     }
29     $("#" + index).hide();
30 }
31
32 function addMulti( count, node, unique_item_fields){
33     var index = $(node).closest("div").attr('id');
34     var countItemsBefore = $("#items_list tbody tr").length;
35     var current_qty = parseInt( $('#quantity').val(), 10 );
36     $("#procModal").modal('show');
37     $("#" + index).hide();
38     for(var i=0;i<count;i++){
39        cloneItemBlock(index, unique_item_fields, function(cloneIndex){
40             addItemInList(cloneIndex,unique_item_fields, function(){
41                     if( ($("#items_list tbody tr").length-countItemsBefore)==(count)){
42                         $("#multiValue").val('');
43                         $('#'+index).appendTo('#outeritemblock');
44                         $('#'+index).show();
45                         $('#'+index + ' #add_multiple_copies' ).css("visibility","hidden");
46                         $("#procModal").modal('hide');
47                     }
48             });
49             $("#" + cloneIndex).find("input[name='buttonPlus']").val( (window.MSG_ADDITEM_JS_UPDATEITEM ) );
50             $("#" + cloneIndex).find("input[name='buttonPlusMulti']").remove();
51             $("#" + cloneIndex).find("input[name='multiValue']").remove();
52             $("#" + cloneIndex).hide();
53             current_qty++;
54             $('#quantity').val( current_qty );
55        });
56     }
57 }
58
59
60 function checkCount(node, unique_item_fields){
61     var count = parseInt( $("#multiValue").val(), 10 );
62     if ( isNaN( count ) || count <=0) {
63         $("#multiCountModal").modal('show');
64     }
65     else{
66         addMulti( count, node, unique_item_fields);
67     }
68 }
69
70 function showItem(index) {
71     $("#outeritemblock").children("div").each(function(){
72         if ( $(this).attr('id') == index ) {
73             $(this).show();
74         } else {
75             if ( $("#items_list table").find('tr[idblock="' + $(this).attr('id') + '"]').length == 0 ) {
76                 $(this).remove();
77             } else {
78                 $(this).hide();
79             }
80         }
81     });
82 }
83
84 function constructTrNode(index, unique_item_fields) {
85     var fields = ['barcode', 'homebranch', 'holdingbranch', 'notforloan',
86         'restricted', 'location', 'itemcallnumber', 'copynumber',
87         'stocknumber', 'ccode', 'itype', 'materials', 'itemnotes'];
88
89     var result = "<tr idblock='" + index + "'>";
90     var edit_link = "<a href='#itemfieldset' style='text-decoration:none' onclick='showItem(\"" + index + "\");'>"
91         + (window.MSG_ADDITEM_JS_EDIT || "Edit") + "</a>";
92     var del_link = "<a style='cursor:pointer' "
93         + "onclick='deleteItemBlock(this, \"" + index + "\", \"" + unique_item_fields + "\");'>"
94         + (window.MSG_ADDITEM_JS_DELETE || "Delete") + "</a>";
95     result += "<td>" + edit_link + "</td>";
96     result += "<td>" + del_link + "</td>";
97     for(i in fields) {
98         var field = fields[i];
99         var field_elt = $("#" + index)
100             .find("[name='kohafield'][value='items."+field+"']")
101             .prevAll("[name='field_value']")[0];
102         var field_value;
103         if($(field_elt).is('select')) {
104             field_value = $(field_elt).find("option:selected").text();
105         } else {
106             field_value = $(field_elt).val();
107         }
108         if (field_value == undefined) {
109             field_value = '';
110         }
111         result += "<td>" + field_value + "</td>";
112     }
113     result += "</tr>";
114
115     return result;
116 }
117
118 function addItemInList(index, unique_item_fields, callback) {
119     $("#items_list").show();
120     var tr = constructTrNode(index, unique_item_fields);
121     $("#items_list table tbody").append(tr);
122     if (typeof callback === "function"){
123         callback();
124     }
125 }
126
127 function deleteItemBlock(node_a, index, unique_item_fields) {
128     $("#" + index).remove();
129     var current_qty = parseInt($("#quantity").val());
130     var max_qty;
131     if($("#quantity_to_receive").length != 0) {
132         max_qty = parseInt($("#quantity_to_receive").val());
133     } else {
134         max_qty = 99999;
135     }
136     $("#quantity").val(current_qty - 1).change();
137     $(node_a).parents('tr').remove();
138     if(current_qty - 1 == 0)
139         $("#items_list").hide();
140
141     if ( $("#quantity").val() <= max_qty - 1) {
142         if ( $("#outeritemblock").children("div :visible").length == 0 ) {
143             $("#outeritemblock").children("div:last").show();
144         }
145     }
146     if ( $("#quantity").val() == 0 && $("#outeritemblock > div").length == 0) {
147         cloneItemBlock(0, unique_item_fields);
148     }
149 }
150
151 function cloneItemBlock(index, unique_item_fields, callback) {
152     var original;
153     if(index) {
154         original = $("#" + index); //original <div>
155     }
156     var dont_copy_fields = new Array();
157     if(unique_item_fields) {
158         var dont_copy_fields = unique_item_fields.split(' ');
159         for(i in dont_copy_fields) {
160             dont_copy_fields[i] = "items." + dont_copy_fields[i];
161         }
162     }
163
164     var random = Math.floor(Math.random()*100000); // get a random itemid.
165     var clone = $("<div id='itemblock"+random+"'></div>")
166     $.ajax({
167         url: "/cgi-bin/koha/services/itemrecorddisplay.pl",
168         dataType: 'html',
169         data: {
170             frameworkcode: 'ACQ'
171         },
172         success: function(data, textStatus, jqXHR) {
173             /* Create the item block */
174             $(clone).append(data);
175             /* Change all itemid fields value */
176             $(clone).find("input[name='itemid']").each(function(){
177                 $(this).val(random);
178             });
179             /* Add buttons + and Clear */
180             var buttonPlus = "<fieldset class=\"action\">";
181                 buttonPlus += '<input type="button" class="addItemControl" name="buttonPlus" style="cursor:pointer; margin:0 1em;" onclick="addItem(this,\'' + unique_item_fields + '\')" value="' + (window.MSG_ADDITEM_JS_ADDITEM || 'Add item')+ '" />';
182                 buttonPlus += '<input type="button" class="addItemControl cancel" name="buttonClear" style="cursor:pointer;" onclick="clearItemBlock(this)" value="' + (window.MSG_ADDITEM_JS_CLEAR || 'Clear')+ '" />';
183                 buttonPlus += '<input type="button" class="addItemControl" name="buttonPlusMulti" onclick="javascript:this.nextSibling.style.display=\'inline\'; return false;" style="cursor:pointer; margin:0 1em;" value="' + (window.MSG_ADDITEM_JS_ADDMULTI || 'Add multiple items')+ '" />';
184                 buttonPlus += '<span id="add_multiple_copies" style="display:none">'
185                             +     '<input type="number" class="addItemControl" id="multiValue" name="multiValue" placeholder="'+window.MSG_ADDITEM_JS_MULTIVAL+'" />'
186                             +     '<input type="button" class="addItemControl" name=buttonAddMulti" style="cursor:pointer; margin:0 1em;" onclick="checkCount( this ,\'' + unique_item_fields + '\')" value="' + (window.MSG_ADDITEM_JS_SUBMITMULTI || 'Add') + '" />'
187                             +     '<div class="dialog message">' + window.MSG_ADDITEM_JS_MULTI_UNIQUE_NOTE + '</div>'
188                             + '</span>';
189                 buttonPlus += "</fieldset>";
190             $(clone).append(buttonPlus);
191             /* Copy values from the original block (input) */
192             $(original).find("input[name='field_value']").each(function(){
193                 var kohafield = $(this).siblings("input[name='kohafield']").val();
194                 if($(this).val() && $.inArray(kohafield,dont_copy_fields) == -1) {
195                     $(this).parent("div").attr("id").match(/^(subfield.)/);
196                     var id = RegExp.$1;
197                     var value = $(this).val();
198                     $(clone).find("div[id^='"+id+"'] input[name='field_value']").val(value);
199                 }
200             });
201             /* Copy values from the original block (select) */
202             $(original).find("select[name='field_value']").each(function(){
203                 var kohafield = $(this).siblings("input[name='kohafield']").val();
204                 if($(this).val() && $.inArray(kohafield,dont_copy_fields) == -1) {
205                     $(this).parent("div").attr("id").match(/^(subfield.)/);
206                     var id = RegExp.$1;
207                     var value = $(this).val();
208                     $(clone).find("div[id^='"+id+"'] select[name='field_value']").val(value);
209                 }
210             });
211
212             $("#outeritemblock").append(clone);
213             if (typeof callback === "function"){
214                 var cloneIndex = "itemblock"+random;
215                 callback(cloneIndex);
216             }
217             BindPluginEvents(data);
218         }
219     });
220 }
221
222 function BindPluginEvents(data) {
223 // the script tag in data for plugins contains a document ready that binds
224 // the events for the plugin
225 // when we append, this code does not get executed anymore; so we do it here
226     var events= data.match(/BindEventstag_\d+_subfield_._\d+/g);
227     if ( events == null ) return;
228     for(var i=0; i<events.length; i++) {
229         window[events[i]]();
230         if( i<events.length-1 && events[i]==events[i+1] ) { i++; }
231             // normally we find the function name twice
232     }
233 }
234
235 function clearItemBlock(node) {
236     var index = $(node).closest("div").attr('id');
237     var block = $("#"+index);
238     $(block).find("input[type='text']").each(function(){
239         $(this).val("");
240     });
241     $(block).find("select").each(function(){
242         $(this).find("option:first").attr("selected", true);
243     });
244 }
245
246 function check_additem(unique_item_fields) {
247     var success = true;
248     var data = new Object();
249     data['field'] = new Array();
250     data['value'] = new Array();
251     var array_fields = unique_item_fields.split(' ');
252     $(".error").empty(); // Clear error div
253
254     // Check if a value is duplicated in form
255     for ( field in array_fields ) {
256         var fieldname = array_fields[field];
257         if (fieldname == '') {
258             continue;
259         }
260         var values = new Array();
261         $("[name='kohafield'][value='items."+ fieldname +"']").each(function(){
262             var input = $(this).prevAll("input[name='field_value']")[0];
263             if($(input).val()) {
264                 values.push($(input).val());
265                 data['field'].push(fieldname);
266                 data['value'].push($(input).val());
267             }
268         });
269
270         var sorted_arr = values.sort();
271         for (var i = 0; i < sorted_arr.length - 1; i += 1) {
272             if (sorted_arr[i + 1] == sorted_arr[i]) {
273                 $(".error").append(
274                     fieldname + " '" + sorted_arr[i] + "' "
275                     + (window.MSG_ADDITEM_JS_IS_DUPLICATE || "is duplicated")
276                     + "<br/>");
277                 success = false;
278             }
279         }
280     }
281
282     // If there is a duplication, we raise an error
283     if ( success == false ) {
284         $(".error").show();
285         return false;
286     }
287
288     $.ajax({
289         url: '/cgi-bin/koha/acqui/check_uniqueness.pl',
290         async: false,
291         dataType: 'json',
292         data: data,
293         success: function(data) {
294             for (field in data) {
295                 success = false;
296                 for (var i=0; i < data[field].length; i++) {
297                     var value = data[field][i];
298                     $(".error").append(
299                         field + " '" + value + "' "
300                         + (window.MSG_ADDITEM_JS_ALREADY_EXISTS_IN_DB
301                             || "already exists in database")
302                         + "<br />"
303                     );
304                 }
305             }
306         }
307     });
308
309     if ( success == false ) {
310         $(".error").show();
311     }
312     return success;
313 }
314