View | Details | Raw Unified | Return to bug 36490
Collapse All | Expand All

(-)a/koha-tmpl/intranet-tmpl/prog/js/staff-global.js (-305 / +399 lines)
Lines 1-108 Link Here
1
/* global shortcut delBasket Sticky AUDIO_ALERT_PATH Cookies */
1
/* global shortcut delBasket Sticky AUDIO_ALERT_PATH Cookies */
2
/* exported addBibToContext delBibToContext escape_str escape_price openWindow _ removeFocus toUC confirmDelete confirmClone playSound */
2
/* exported addBibToContext delBibToContext escape_str escape_price openWindow _ removeFocus toUC confirmDelete confirmClone playSound */
3
if ( KOHA === undefined ) var KOHA = {};
3
if (KOHA === undefined) var KOHA = {};
4
4
5
function _(s) { return s; } // dummy function for gettext
5
function _(s) {
6
    return s;
7
} // dummy function for gettext
6
8
7
// http://stackoverflow.com/questions/1038746/equivalent-of-string-format-in-jquery/5341855#5341855
9
// http://stackoverflow.com/questions/1038746/equivalent-of-string-format-in-jquery/5341855#5341855
8
String.prototype.format = function() { return formatstr(this, arguments); };
10
String.prototype.format = function () {
11
    return formatstr(this, arguments);
12
};
9
function formatstr(str, col) {
13
function formatstr(str, col) {
10
    col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);
14
    col =
15
        typeof col === "object"
16
            ? col
17
            : Array.prototype.slice.call(arguments, 1);
11
    var idx = 0;
18
    var idx = 0;
12
    return str.replace(/%%|%s|%(\d+)\$s/g, function (m, n) {
19
    return str.replace(/%%|%s|%(\d+)\$s/g, function (m, n) {
13
        if (m == "%%") { return "%"; }
20
        if (m == "%%") {
14
        if (m == "%s") { return col[idx++]; }
21
            return "%";
22
        }
23
        if (m == "%s") {
24
            return col[idx++];
25
        }
15
        return col[n];
26
        return col[n];
16
    });
27
    });
17
}
28
}
18
29
19
var HtmlCharsToEscape = {
30
var HtmlCharsToEscape = {
20
    '&': '&',
31
    "&": "&",
21
    '<': '&lt;',
32
    "<": "&lt;",
22
    '>': '&gt;'
33
    ">": "&gt;",
23
};
34
};
24
String.prototype.escapeHtml = function() {
35
String.prototype.escapeHtml = function () {
25
    return this.replace(/[&<>]/g, function(c) {
36
    return this.replace(/[&<>]/g, function (c) {
26
        return HtmlCharsToEscape[c] || c;
37
        return HtmlCharsToEscape[c] || c;
27
    });
38
    });
28
};
39
};
29
function escape_str(s){
40
function escape_str(s) {
30
    return s != null ? s.escapeHtml() : "";
41
    return s != null ? s.escapeHtml() : "";
31
}
42
}
32
43
33
/*
44
/*
34
 * Void method for numbers, for consistency
45
 * Void method for numbers, for consistency
35
 */
46
 */
36
Number.prototype.escapeHtml = function() {
47
Number.prototype.escapeHtml = function () {
37
    return this;
48
    return this;
38
};
49
};
39
function escape_price(p){
50
function escape_price(p) {
40
    return p != null ? p.escapeHtml().format_price() : "";
51
    return p != null ? p.escapeHtml().format_price() : "";
41
}
52
}
42
53
43
// http://stackoverflow.com/questions/14859281/select-tab-by-name-in-jquery-ui-1-10-0/16550804#16550804
54
// http://stackoverflow.com/questions/14859281/select-tab-by-name-in-jquery-ui-1-10-0/16550804#16550804
44
$.fn.tabIndex = function () {
55
$.fn.tabIndex = function () {
45
    return $(this).parent().children('div').index(this);
56
    return $(this).parent().children("div").index(this);
46
};
57
};
47
$.fn.selectTabByID = function (tabID) {
58
$.fn.selectTabByID = function (tabID) {
48
    $("a[href='" + tabID + "']", $(this) ).tab("show");
59
    $("a[href='" + tabID + "']", $(this)).tab("show");
49
};
60
};
50
61
51
$(document).ready(function() {
62
$(document).ready(function () {
52
53
    //check for a hash before setting focus
63
    //check for a hash before setting focus
54
    let hash = window.location.hash;
64
    let hash = window.location.hash;
55
    if ( ! hash ) {
65
    if (!hash) {
56
        $(".tab-pane.active input:text:first").focus();
66
        $(".tab-pane.active input:text:first").focus();
57
    }
67
    }
58
    $("#header_search a[data-toggle='tab']").on("shown.bs.tab", function (e) {
68
    $("#header_search a[data-toggle='tab']").on("shown.bs.tab", function (e) {
59
        $( e.target.hash ).find("input:text:first").focus();
69
        $(e.target.hash).find("input:text:first").focus();
60
    });
70
    });
61
71
62
    $(".close, .close_window").on("click", function(e){
72
    $(".close, .close_window").on("click", function (e) {
63
        e.preventDefault();
73
        e.preventDefault();
64
        window.close();
74
        window.close();
65
    });
75
    });
66
76
67
    $("#checkin_search form").preventDoubleFormSubmit();
77
    $("#checkin_search_panel form").preventDoubleFormSubmit();
68
78
69
    if($("#header_search #checkin_search").length > 0){
79
    if ($("#header_search #checkin_search_panel").length > 0) {
70
        shortcut.add('Alt+r',function (){
80
        shortcut.add("Alt+r", function () {
71
            $("#header_search").selectTabByID("#checkin_search");
81
            $("#header_search").selectTabByID("#checkin_search_panel");
72
            $("#ret_barcode").focus();
82
            $("#ret_barcode").focus();
73
        });
83
        });
74
    } else {
84
    } else {
75
        shortcut.add('Alt+r',function (){
85
        shortcut.add("Alt+r", function () {
76
            location.href="/cgi-bin/koha/circ/returns.pl"; });
86
            location.href = "/cgi-bin/koha/circ/returns.pl";
87
        });
77
    }
88
    }
78
    if($("#header_search #circ_search").length > 0){
89
    if ($("#header_search #circ_search_panel").length > 0) {
79
        shortcut.add('Alt+u',function (){
90
        shortcut.add("Alt+u", function () {
80
            $("#header_search").selectTabByID("#circ_search");
91
            $("#header_search").selectTabByID("#circ_search_panel");
81
            $("#findborrower").focus();
92
            $("#findborrower").focus();
82
        });
93
        });
83
    } else {
94
    } else {
84
        shortcut.add('Alt+u',function(){ location.href="/cgi-bin/koha/circ/circulation.pl"; });
95
        shortcut.add("Alt+u", function () {
96
            location.href = "/cgi-bin/koha/circ/circulation.pl";
97
        });
85
    }
98
    }
86
    if($("#header_search #catalog_search").length > 0){
99
    if ($("#header_search #catalog_search_panel").length > 0) {
87
        shortcut.add('Alt+q',function (){
100
        shortcut.add("Alt+q", function () {
88
            $("#header_search").selectTabByID("#catalog_search");
101
            $("#header_search").selectTabByID("#catalog_search_panel");
89
            $("#search-form").focus();
102
            $("#search-form").focus();
90
        });
103
        });
91
    } else {
104
    } else {
92
        shortcut.add('Alt+q',function(){ location.href="/cgi-bin/koha/catalogue/search.pl"; });
105
        shortcut.add("Alt+q", function () {
106
            location.href = "/cgi-bin/koha/catalogue/search.pl";
107
        });
93
    }
108
    }
94
    if($("#header_search #renew_search").length > 0){
109
    if ($("#header_search #renew_search_panel").length > 0) {
95
        shortcut.add('Alt+w',function (){
110
        shortcut.add("Alt+w", function () {
96
            $("#header_search").selectTabByID("#renew_search");
111
            $("#header_search").selectTabByID("#renew_search_panel");
97
            $("#ren_barcode").focus();
112
            $("#ren_barcode").focus();
98
        });
113
        });
99
    } else {
114
    } else {
100
        shortcut.add('Alt+w',function(){ location.href="/cgi-bin/koha/circ/renew.pl"; });
115
        shortcut.add("Alt+w", function () {
116
            location.href = "/cgi-bin/koha/circ/renew.pl";
117
        });
101
    }
118
    }
102
119
103
    $('#header_search .form-extra-content-toggle').on('click', function () {
120
    $("#header_search .form-extra-content-toggle").on("click", function () {
104
        const extraContent = $(this).closest('form').find('.form-extra-content');
121
        const extraContent = $(this)
105
        if (extraContent.is(':visible')) {
122
            .closest("form")
123
            .find(".form-extra-content");
124
        if (extraContent.is(":visible")) {
106
            extraContent.hide();
125
            extraContent.hide();
107
            $(this).removeClass("extra-content-open");
126
            $(this).removeClass("extra-content-open");
108
        } else {
127
        } else {
Lines 112-201 $(document).ready(function() { Link Here
112
    });
131
    });
113
132
114
    $(".focus").focus();
133
    $(".focus").focus();
115
    $(".validated").each(function() {
134
    $(".validated").each(function () {
116
        $(this).validate();
135
        $(this).validate();
117
    });
136
    });
118
    jQuery.validator.addClassRules("decimal", {
137
    jQuery.validator.addClassRules("decimal", {
119
        number: true
138
        number: true,
120
    });
139
    });
121
140
122
    $("#logout").on("click",function(){
141
    $("#logout").on("click", function () {
123
        logOut();
142
        logOut();
124
    });
143
    });
125
    $("#helper").on("click",function(){
144
    $("#helper").on("click", function () {
126
        openHelp();
145
        openHelp();
127
        return false;
146
        return false;
128
    });
147
    });
129
148
130
    $("body").on("keypress", ".noEnterSubmit", function(e){
149
    $("body").on("keypress", ".noEnterSubmit", function (e) {
131
        return checkEnter(e);
150
        return checkEnter(e);
132
    });
151
    });
133
152
134
    $("#header_search .nav-tabs a").on("click",function(){
153
    $("#header_search .nav-tabs a").on("click", function () {
135
        var field_index = $(this).parent().index();
154
        var field_index = $(this).parent().index();
136
        keep_text( field_index );
155
        keep_text(field_index);
137
    });
156
    });
138
157
139
    $(".toggle_element").on("click",function(e){
158
    $(".toggle_element").on("click", function (e) {
140
        e.preventDefault();
159
        e.preventDefault();
141
        $( $(this).data("element") ).toggle();
160
        $($(this).data("element")).toggle();
142
        if (typeof Sticky !== "undefined" && typeof hcSticky === "function") {
161
        if (typeof Sticky !== "undefined" && typeof hcSticky === "function") {
143
            Sticky.hcSticky('update');
162
            Sticky.hcSticky("update");
144
        }
163
        }
145
    });
164
    });
146
165
147
    var navmenulist = $("#navmenulist");
166
    var navmenulist = $("#navmenulist");
148
    if( navmenulist.length > 0 ){
167
    if (navmenulist.length > 0) {
149
        var path = location.pathname.substring(1);
168
        var path = location.pathname.substring(1);
150
        var url = window.location.toString();
169
        var url = window.location.toString();
151
        var params = '';
170
        var params = "";
152
        if ( url.match(/\?(.+)$/) ) {
171
        if (url.match(/\?(.+)$/)) {
153
            params = "?" + RegExp.$1;
172
            params = "?" + RegExp.$1;
154
        }
173
        }
155
        if ($("a[href$=\"/" + path + params + "\"]", navmenulist).length == 0){
174
        if ($('a[href$="/' + path + params + '"]', navmenulist).length == 0) {
156
            $("a[href$=\"/" + path + "\"]", navmenulist).addClass("current");
175
            $('a[href$="/' + path + '"]', navmenulist).addClass("current");
157
        } else {
176
        } else {
158
            $("a[href$=\"/" + path + params + "\"]", navmenulist).addClass("current");
177
            $('a[href$="/' + path + params + '"]', navmenulist).addClass(
178
                "current"
179
            );
159
        }
180
        }
160
    }
181
    }
161
182
162
    $("#catalog-search-link a").on("mouseenter mouseleave", function(){
183
    $("#catalog-search-link a").on("mouseenter mouseleave", function () {
163
        $("#catalog-search-dropdown a").toggleClass("catalog-search-dropdown-hover");
184
        $("#catalog-search-dropdown a").toggleClass(
185
            "catalog-search-dropdown-hover"
186
        );
164
    });
187
    });
165
188
166
    if ( localStorage.getItem("previousPatrons") || $("#hiddenborrowernumber").val() ){
189
    if (
190
        localStorage.getItem("previousPatrons") ||
191
        $("#hiddenborrowernumber").val()
192
    ) {
167
        var previous_patrons = [];
193
        var previous_patrons = [];
168
        if ( localStorage.getItem("previousPatrons") ) {
194
        if (localStorage.getItem("previousPatrons")) {
169
            previous_patrons = JSON.parse(localStorage.getItem("previousPatrons"));
195
            previous_patrons = JSON.parse(
196
                localStorage.getItem("previousPatrons")
197
            );
170
        }
198
        }
171
199
172
        if ( $("#hiddenborrowernumber").val() ) {
200
        if ($("#hiddenborrowernumber").val()) {
173
            // Remove this patron from the list if they are already there
201
            // Remove this patron from the list if they are already there
174
            previous_patrons = previous_patrons.filter(function (p) {
202
            previous_patrons = previous_patrons.filter(function (p) {
175
                return p["borrowernumber"] != $("#hiddenborrowernumber").val();
203
                return p["borrowernumber"] != $("#hiddenborrowernumber").val();
176
            });
204
            });
177
205
178
            const previous_patron = {
206
            const previous_patron = {
179
                "borrowernumber": $("#hiddenborrowernumber").val(),
207
                borrowernumber: $("#hiddenborrowernumber").val(),
180
                "name": $("#hiddenborrowername").val(),
208
                name: $("#hiddenborrowername").val(),
181
                "card": $("#hiddenborrowercard").val()
209
                card: $("#hiddenborrowercard").val(),
182
            };
210
            };
183
211
184
            previous_patrons.unshift( previous_patron );
212
            previous_patrons.unshift(previous_patron);
185
            // Limit to number of patrons specified in showLastPatronCount
213
            // Limit to number of patrons specified in showLastPatronCount
186
            if ( previous_patrons.length > showLastPatronCount ) previous_patrons.pop();
214
            if (previous_patrons.length > showLastPatronCount)
187
            localStorage.setItem("previousPatrons", JSON.stringify(previous_patrons));
215
                previous_patrons.pop();
216
            localStorage.setItem(
217
                "previousPatrons",
218
                JSON.stringify(previous_patrons)
219
            );
188
        }
220
        }
189
221
190
        if ( previous_patrons.length ) {
222
        if (previous_patrons.length) {
191
            let p = previous_patrons[0];
223
            let p = previous_patrons[0];
192
            $("#lastborrowerlink").show();
224
            $("#lastborrowerlink").show();
193
            $("#lastborrowerlink").prop("title", `${p["name"]} (${p["card"]})`);
225
            $("#lastborrowerlink").prop("title", `${p["name"]} (${p["card"]})`);
194
            $("#lastborrowerlink").prop("href", `/cgi-bin/koha/circ/circulation.pl?borrowernumber=${p["borrowernumber"]}`);
226
            $("#lastborrowerlink").prop(
227
                "href",
228
                `/cgi-bin/koha/circ/circulation.pl?borrowernumber=${p["borrowernumber"]}`
229
            );
195
            $("#lastborrower-window").css("display", "inline-flex");
230
            $("#lastborrower-window").css("display", "inline-flex");
196
231
197
            previous_patrons.reverse();
232
            previous_patrons.reverse();
198
            for ( i in previous_patrons ) {
233
            for (i in previous_patrons) {
199
                p = previous_patrons[i];
234
                p = previous_patrons[i];
200
                const el = `<li><a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=${p["borrowernumber"]}">${p["name"]} (${p["card"]})</a></li>`;
235
                const el = `<li><a href="/cgi-bin/koha/circ/circulation.pl?borrowernumber=${p["borrowernumber"]}">${p["name"]} (${p["card"]})</a></li>`;
201
                $("#lastBorrowerList").prepend(el);
236
                $("#lastBorrowerList").prepend(el);
Lines 203-234 $(document).ready(function() { Link Here
203
        }
238
        }
204
    }
239
    }
205
240
206
    if( $("#hiddenborrowernumber").val() ){
241
    if ($("#hiddenborrowernumber").val()) {
207
        localStorage.setItem("currentborrowernumber", $("#hiddenborrowernumber").val() );
242
        localStorage.setItem(
243
            "currentborrowernumber",
244
            $("#hiddenborrowernumber").val()
245
        );
208
    }
246
    }
209
247
210
    $("#lastborrower-remove").click(function() {
248
    $("#lastborrower-remove").click(function () {
211
        removeLastBorrower();
249
        removeLastBorrower();
212
        $("#lastborrower-window").hide();
250
        $("#lastborrower-window").hide();
213
    });
251
    });
214
252
215
    /* Search results browsing */
253
    /* Search results browsing */
216
    /* forms with action leading to search */
254
    /* forms with action leading to search */
217
    $("form[action*='search.pl']").submit(function(){
255
    $("form[action*='search.pl']").submit(function () {
218
        $('[name^="limit"]').each(function(){
256
        $('[name^="limit"]').each(function () {
219
            if( $(this).val() == '' ){
257
            if ($(this).val() == "") {
220
                $(this).prop("disabled","disabled");
258
                $(this).prop("disabled", "disabled");
221
            }
259
            }
222
        });
260
        });
223
        var disabledPrior = false;
261
        var disabledPrior = false;
224
        $(".search-term-row").each(function(){
262
        $(".search-term-row").each(function () {
225
            if( disabledPrior ){
263
            if (disabledPrior) {
226
                $(this).find('select[name="op"]').prop("disabled","disabled");
264
                $(this).find('select[name="op"]').prop("disabled", "disabled");
227
                disabledPrior = false;
265
                disabledPrior = false;
228
            }
266
            }
229
            if( $(this).find('input[name="q"]').val() == "" ){
267
            if ($(this).find('input[name="q"]').val() == "") {
230
                $(this).find('input').prop("disabled","disabled");
268
                $(this).find("input").prop("disabled", "disabled");
231
                $(this).find('select').prop("disabled","disabled");
269
                $(this).find("select").prop("disabled", "disabled");
232
                disabledPrior = true;
270
                disabledPrior = true;
233
            }
271
            }
234
        });
272
        });
Lines 236-280 $(document).ready(function() { Link Here
236
        saveOrClearSimpleSearchParams();
274
        saveOrClearSimpleSearchParams();
237
    });
275
    });
238
    /* any link to launch a search except navigation links */
276
    /* any link to launch a search except navigation links */
239
    $("[href*='search.pl?']").not(".nav").not('.searchwithcontext').click(function(){
277
    $("[href*='search.pl?']")
240
        resetSearchContext();
278
        .not(".nav")
241
    });
279
        .not(".searchwithcontext")
280
        .click(function () {
281
            resetSearchContext();
282
        });
242
    /* any link to a detail page from the results page. */
283
    /* any link to a detail page from the results page. */
243
    $("#bookbag_form a[href*='detail.pl?']").click(function(){
284
    $("#bookbag_form a[href*='detail.pl?']").click(function () {
244
        resetSearchContext();
285
        resetSearchContext();
245
    });
286
    });
246
247
});
287
});
248
288
249
function removeLastBorrower(){
289
function removeLastBorrower() {
250
    localStorage.removeItem("previousPatrons");
290
    localStorage.removeItem("previousPatrons");
251
}
291
}
252
292
253
// http://jennifermadden.com/javascript/stringEnterKeyDetector.html
293
// http://jennifermadden.com/javascript/stringEnterKeyDetector.html
254
function checkEnter(e){ //e is event object passed from function invocation
294
function checkEnter(e) {
295
    //e is event object passed from function invocation
255
    var characterCode; // literal character code will be stored in this variable
296
    var characterCode; // literal character code will be stored in this variable
256
    if(e && e.which){ //if which property of event object is supported (NN4)
297
    if (e && e.which) {
298
        //if which property of event object is supported (NN4)
257
        characterCode = e.which; //character code is contained in NN4's which property
299
        characterCode = e.which; //character code is contained in NN4's which property
258
    } else {
300
    } else {
259
        characterCode = e.keyCode; //character code is contained in IE's keyCode property
301
        characterCode = e.keyCode; //character code is contained in IE's keyCode property
260
    }
302
    }
261
    if( characterCode == 13 //if generated character code is equal to ascii 13 (if enter key)
303
    if (
262
        && e.target.nodeName == "INPUT"
304
        characterCode == 13 && //if generated character code is equal to ascii 13 (if enter key)
263
        && e.target.type != "submit" // Allow enter to submit using the submit button
305
        e.target.nodeName == "INPUT" &&
264
    ){
306
        e.target.type != "submit" // Allow enter to submit using the submit button
307
    ) {
265
        return false;
308
        return false;
266
    } else {
309
    } else {
267
        return true;
310
        return true;
268
    }
311
    }
269
}
312
}
270
313
271
function clearHoldFor(){
314
function clearHoldFor() {
272
    Cookies.remove("holdfor", { path: '/', SameSite: 'Lax' });
315
    Cookies.remove("holdfor", { path: "/", SameSite: "Lax" });
273
}
316
}
274
317
275
function logOut(){
318
function logOut() {
276
    if( typeof delBasket == 'function' ){
319
    if (typeof delBasket == "function") {
277
        delBasket('main', true);
320
        delBasket("main", true);
278
    }
321
    }
279
    clearHoldFor();
322
    clearHoldFor();
280
    removeLastBorrower();
323
    removeLastBorrower();
Lines 285-313 function logOut(){ Link Here
285
    localStorage.removeItem("item_search_selections");
328
    localStorage.removeItem("item_search_selections");
286
}
329
}
287
330
288
function openHelp(){
331
function openHelp() {
289
    window.open( "/cgi-bin/koha/help.pl", "_blank");
332
    window.open("/cgi-bin/koha/help.pl", "_blank");
290
}
333
}
291
334
292
jQuery.fn.preventDoubleFormSubmit = function() {
335
jQuery.fn.preventDoubleFormSubmit = function () {
293
    jQuery(this).submit(function() {
336
    jQuery(this).submit(function () {
294
        $("body, form input[type='submit'], form button[type='submit'], form a").addClass('waiting');
337
        $(
295
        if (this.beenSubmitted)
338
            "body, form input[type='submit'], form button[type='submit'], form a"
296
            return false;
339
        ).addClass("waiting");
297
        else
340
        if (this.beenSubmitted) return false;
298
            this.beenSubmitted = true;
341
        else this.beenSubmitted = true;
299
    });
342
    });
300
};
343
};
301
344
302
function openWindow(link,name,width,height) {
345
function openWindow(link, name, width, height) {
303
    name = (typeof name == "undefined")?'popup':name;
346
    name = typeof name == "undefined" ? "popup" : name;
304
    width = (typeof width == "undefined")?'600':width;
347
    width = typeof width == "undefined" ? "600" : width;
305
    height = (typeof height == "undefined")?'400':height;
348
    height = typeof height == "undefined" ? "400" : height;
306
    //IE <= 9 can't handle a "name" with whitespace
349
    //IE <= 9 can't handle a "name" with whitespace
307
    try {
350
    try {
308
        window.open(link,name,'width='+width+',height='+height+',resizable=yes,toolbar=false,scrollbars=yes,top');
351
        window.open(
309
    } catch(e) {
352
            link,
310
        window.open(link,null,'width='+width+',height='+height+',resizable=yes,toolbar=false,scrollbars=yes,top');
353
            name,
354
            "width=" +
355
                width +
356
                ",height=" +
357
                height +
358
                ",resizable=yes,toolbar=false,scrollbars=yes,top"
359
        );
360
    } catch (e) {
361
        window.open(
362
            link,
363
            null,
364
            "width=" +
365
                width +
366
                ",height=" +
367
                height +
368
                ",resizable=yes,toolbar=false,scrollbars=yes,top"
369
        );
311
    }
370
    }
312
}
371
}
313
372
Lines 315-342 function openWindow(link,name,width,height) { Link Here
315
// repeated scanning actions on errors so the librarian doesn't
374
// repeated scanning actions on errors so the librarian doesn't
316
// continue scanning and miss the error.
375
// continue scanning and miss the error.
317
function removeFocus() {
376
function removeFocus() {
318
    $(':focus').blur();
377
    $(":focus").blur();
319
}
378
}
320
379
321
function toUC(f) {
380
function toUC(f) {
322
    var x=f.value.toUpperCase();
381
    var x = f.value.toUpperCase();
323
    f.value=x;
382
    f.value = x;
324
    return true;
383
    return true;
325
}
384
}
326
385
327
function confirmDelete(message) {
386
function confirmDelete(message) {
328
    return (confirm(message) ? true : false);
387
    return confirm(message) ? true : false;
329
}
388
}
330
389
331
function confirmClone(message) {
390
function confirmClone(message) {
332
    return (confirm(message) ? true : false);
391
    return confirm(message) ? true : false;
333
}
392
}
334
393
335
function playSound( sound ) {
394
function playSound(sound) {
336
    if ( ! ( sound.indexOf('http://') === 0 || sound.indexOf('https://') === 0  ) ) {
395
    if (!(sound.indexOf("http://") === 0 || sound.indexOf("https://") === 0)) {
337
        sound = AUDIO_ALERT_PATH + sound;
396
        sound = AUDIO_ALERT_PATH + sound;
338
    }
397
    }
339
    document.getElementById("audio-alert").innerHTML = '<audio src="' + sound + '" autoplay="autoplay" autobuffer="autobuffer"></audio>';
398
    document.getElementById("audio-alert").innerHTML =
399
        '<audio src="' +
400
        sound +
401
        '" autoplay="autoplay" autobuffer="autobuffer"></audio>';
340
}
402
}
341
403
342
// For keeping the text when navigating the search tabs
404
// For keeping the text when navigating the search tabs
Lines 345-352 function keep_text(clicked_index) { Link Here
345
    var persist = searchboxes[0].value;
407
    var persist = searchboxes[0].value;
346
408
347
    for (var i = 0; i < searchboxes.length - 1; i++) {
409
    for (var i = 0; i < searchboxes.length - 1; i++) {
348
        if (searchboxes[i].value != searchboxes[i+1].value) {
410
        if (searchboxes[i].value != searchboxes[i + 1].value) {
349
            if (i === searchboxes.length-2) {
411
            if (i === searchboxes.length - 2) {
350
                if (searchboxes[i].value != searchboxes[0].value) {
412
                if (searchboxes[i].value != searchboxes[0].value) {
351
                    persist = searchboxes[i].value;
413
                    persist = searchboxes[i].value;
352
                } else if (searchboxes.length === 2) {
414
                } else if (searchboxes.length === 2) {
Lines 354-363 function keep_text(clicked_index) { Link Here
354
                        persist = searchboxes[1].value;
416
                        persist = searchboxes[1].value;
355
                    }
417
                    }
356
                } else {
418
                } else {
357
                    persist = searchboxes[i+1].value;
419
                    persist = searchboxes[i + 1].value;
358
                }
420
                }
359
            } else if (searchboxes[i+1].value != searchboxes[i+2].value) {
421
            } else if (searchboxes[i + 1].value != searchboxes[i + 2].value) {
360
                persist = searchboxes[i+1].value;
422
                persist = searchboxes[i + 1].value;
361
            }
423
            }
362
        }
424
        }
363
    }
425
    }
Lines 368-409 function keep_text(clicked_index) { Link Here
368
}
430
}
369
431
370
// Extends jQuery API
432
// Extends jQuery API
371
jQuery.extend({uniqueArray:function(array){
433
jQuery.extend({
372
    return $.grep(array, function(el, index) {
434
    uniqueArray: function (array) {
373
        return index === $.inArray(el, array);
435
        return $.grep(array, function (el, index) {
374
    });
436
            return index === $.inArray(el, array);
375
}});
437
        });
438
    },
439
});
376
440
377
function removeByValue(arr, val) {
441
function removeByValue(arr, val) {
378
    for(var i=0; i<arr.length; i++) {
442
    for (var i = 0; i < arr.length; i++) {
379
        if(arr[i] == val) {
443
        if (arr[i] == val) {
380
            arr.splice(i, 1);
444
            arr.splice(i, 1);
381
            break;
445
            break;
382
        }
446
        }
383
    }
447
    }
384
}
448
}
385
449
386
function addBibToContext( bibnum ) {
450
function addBibToContext(bibnum) {
387
    bibnum = parseInt(bibnum, 10);
451
    bibnum = parseInt(bibnum, 10);
388
    var bibnums = getContextBiblioNumbers();
452
    var bibnums = getContextBiblioNumbers();
389
    bibnums.push(bibnum);
453
    bibnums.push(bibnum);
390
    setContextBiblioNumbers( bibnums );
454
    setContextBiblioNumbers(bibnums);
391
    setContextBiblioNumbers( $.uniqueArray( bibnums ) );
455
    setContextBiblioNumbers($.uniqueArray(bibnums));
392
}
456
}
393
457
394
function delBibToContext( bibnum ) {
458
function delBibToContext(bibnum) {
395
    var bibnums = getContextBiblioNumbers();
459
    var bibnums = getContextBiblioNumbers();
396
    removeByValue( bibnums, bibnum );
460
    removeByValue(bibnums, bibnum);
397
    setContextBiblioNumbers( $.uniqueArray( bibnums ) );
461
    setContextBiblioNumbers($.uniqueArray(bibnums));
398
}
462
}
399
463
400
function setContextBiblioNumbers( bibnums ) {
464
function setContextBiblioNumbers(bibnums) {
401
    localStorage.setItem('bibs_selected', JSON.stringify( bibnums ) );
465
    localStorage.setItem("bibs_selected", JSON.stringify(bibnums));
402
}
466
}
403
467
404
function getContextBiblioNumbers() {
468
function getContextBiblioNumbers() {
405
    var r = localStorage.getItem('bibs_selected');
469
    var r = localStorage.getItem("bibs_selected");
406
    if ( r ) {
470
    if (r) {
407
        return JSON.parse(r);
471
        return JSON.parse(r);
408
    }
472
    }
409
    r = new Array();
473
    r = new Array();
Lines 411-435 function getContextBiblioNumbers() { Link Here
411
}
475
}
412
476
413
function resetSearchContext() {
477
function resetSearchContext() {
414
    setContextBiblioNumbers( new Array() );
478
    setContextBiblioNumbers(new Array());
415
}
479
}
416
480
417
function saveOrClearSimpleSearchParams() {
481
function saveOrClearSimpleSearchParams() {
418
    // Simple masthead search - pass value for display on details page
482
    // Simple masthead search - pass value for display on details page
419
    var pulldown_selection;
483
    var pulldown_selection;
420
    var searchbox_value;
484
    var searchbox_value;
421
    if( $("#cat-search-block select.advsearch").length ){
485
    if ($("#cat-search-block select.advsearch").length) {
422
        pulldown_selection = $("#cat-search-block select.advsearch").val();
486
        pulldown_selection = $("#cat-search-block select.advsearch").val();
423
    } else {
487
    } else {
424
        pulldown_selection ="";
488
        pulldown_selection = "";
425
    }
489
    }
426
    if( $("#cat-search-block #search-form").length ){
490
    if ($("#cat-search-block #search-form").length) {
427
        searchbox_value = $("#cat-search-block #search-form").val();
491
        searchbox_value = $("#cat-search-block #search-form").val();
428
    } else {
492
    } else {
429
        searchbox_value ="";
493
        searchbox_value = "";
430
    }
494
    }
431
    localStorage.setItem('cat_search_pulldown_selection', pulldown_selection );
495
    localStorage.setItem("cat_search_pulldown_selection", pulldown_selection);
432
    localStorage.setItem('searchbox_value', searchbox_value );
496
    localStorage.setItem("searchbox_value", searchbox_value);
433
}
497
}
434
498
435
function patron_autocomplete(node, options) {
499
function patron_autocomplete(node, options) {
Lines 438-562 function patron_autocomplete(node, options) { Link Here
438
    let on_select_callback;
502
    let on_select_callback;
439
503
440
    if (options) {
504
    if (options) {
441
        if (options['link-to']) {
505
        if (options["link-to"]) {
442
            link_to = options['link-to'];
506
            link_to = options["link-to"];
443
        }
507
        }
444
        if (options['url-params']) {
508
        if (options["url-params"]) {
445
            url_params = options['url-params'];
509
            url_params = options["url-params"];
446
        }
510
        }
447
        if (options['on-select-callback']) {
511
        if (options["on-select-callback"]) {
448
            on_select_callback = options['on-select-callback'];
512
            on_select_callback = options["on-select-callback"];
449
        }
513
        }
450
    }
514
    }
451
    return node.autocomplete({
515
    return (node
452
        source: function (request, response) {
516
        .autocomplete({
453
            let q = buildPatronSearchQuery(request.term);
517
            source: function (request, response) {
454
518
                let q = buildPatronSearchQuery(request.term);
455
            let params = {
519
456
                '_page': 1,
520
                let params = {
457
                '_per_page': 10,
521
                    _page: 1,
458
                'q': JSON.stringify(q),
522
                    _per_page: 10,
459
                '_order_by': '+me.surname,+me.firstname',
523
                    q: JSON.stringify(q),
460
            };
524
                    _order_by: "+me.surname,+me.firstname",
461
            $.ajax({
525
                };
462
                data: params,
526
                $.ajax({
463
                type: 'GET',
527
                    data: params,
464
                url: '/api/v1/patrons',
528
                    type: "GET",
465
                headers: {
529
                    url: "/api/v1/patrons",
466
                    "x-koha-embed": "library"
530
                    headers: {
467
                },
531
                        "x-koha-embed": "library",
468
                success: function (data) {
532
                    },
469
                    return response(data);
533
                    success: function (data) {
470
                },
534
                        return response(data);
471
                error: function (e) {
535
                    },
472
                    if (e.state() != 'rejected') {
536
                    error: function (e) {
473
                        alert(__("An error occurred. Check the logs for details."));
537
                        if (e.state() != "rejected") {
474
                    }
538
                            alert(
475
                    return response();
539
                                __(
540
                                    "An error occurred. Check the logs for details."
541
                                )
542
                            );
543
                        }
544
                        return response();
545
                    },
546
                });
547
            },
548
            minLength: 3,
549
            select: function (event, ui) {
550
                if (ui.item.link) {
551
                    window.location.href = ui.item.link;
552
                } else if (on_select_callback) {
553
                    return on_select_callback(event, ui);
476
                }
554
                }
477
            });
555
            },
478
        },
556
            focus: function (event, ui) {
479
        minLength: 3,
557
                event.preventDefault(); // Don't replace the text field
480
        select: function (event, ui) {
558
            },
481
            if (ui.item.link) {
559
        })
482
                window.location.href = ui.item.link;
560
        .data("ui-autocomplete")._renderItem = function (ul, item) {
483
            } else if (on_select_callback) {
561
        if (link_to) {
484
                return on_select_callback(event, ui);
562
            item.link =
485
            }
563
                link_to == "circ"
486
        },
487
        focus: function (event, ui) {
488
            event.preventDefault(); // Don't replace the text field
489
        },
490
    })
491
        .data("ui-autocomplete")
492
        ._renderItem = function (ul, item) {
493
            if (link_to) {
494
                item.link = link_to == 'circ'
495
                    ? "/cgi-bin/koha/circ/circulation.pl"
564
                    ? "/cgi-bin/koha/circ/circulation.pl"
496
                    : link_to == 'reserve'
565
                    : link_to == "reserve"
497
                        ? "/cgi-bin/koha/reserve/request.pl"
566
                    ? "/cgi-bin/koha/reserve/request.pl"
498
                        : "/cgi-bin/koha/members/moremember.pl";
567
                    : "/cgi-bin/koha/members/moremember.pl";
499
                item.link += (url_params ? '?' + url_params + '&' : "?") + 'borrowernumber=' + item.patron_id;
568
            item.link +=
500
            } else {
569
                (url_params ? "?" + url_params + "&" : "?") +
501
                item.link = null;
570
                "borrowernumber=" +
502
            }
571
                item.patron_id;
572
        } else {
573
            item.link = null;
574
        }
503
575
504
            var cardnumber = "";
576
        var cardnumber = "";
505
            if (item.cardnumber != "") {
577
        if (item.cardnumber != "") {
506
                // Display card number in parentheses if it exists
578
            // Display card number in parentheses if it exists
507
                cardnumber = " (" + item.cardnumber + ") ";
579
            cardnumber = " (" + item.cardnumber + ") ";
508
            }
580
        }
509
            if (item.library_id == loggedInLibrary) {
581
        if (item.library_id == loggedInLibrary) {
510
                loggedInClass = "ac-currentlibrary";
582
            loggedInClass = "ac-currentlibrary";
511
            } else {
583
        } else {
512
                loggedInClass = "";
584
            loggedInClass = "";
513
            }
585
        }
514
            return $("<li></li>")
586
        return $("<li></li>")
515
                .addClass(loggedInClass)
587
            .addClass(loggedInClass)
516
                .data("ui-autocomplete-item", item)
588
            .data("ui-autocomplete-item", item)
517
                .append(
589
            .append(
518
                    ""
590
                "" +
519
                    + (item.link ? "<a href=\"" + item.link + "\">" : "<a>")
591
                    (item.link ? '<a href="' + item.link + '">' : "<a>") +
520
                    + (item.surname ? item.surname.escapeHtml() : "") + ", "
592
                    (item.surname ? item.surname.escapeHtml() : "") +
521
                    + (item.firstname ? item.firstname.escapeHtml() : "")
593
                    ", " +
522
                    + " " + (item.middle_name ? item.middle_name.escapeHtml() : "")
594
                    (item.firstname ? item.firstname.escapeHtml() : "") +
523
                    + cardnumber.escapeHtml()
595
                    " " +
524
                    + " <small>"
596
                    (item.middle_name ? item.middle_name.escapeHtml() : "") +
525
                    + (item.date_of_birth
597
                    cardnumber.escapeHtml() +
526
                        ? $date(item.date_of_birth)
598
                    " <small>" +
527
                        + "<span class=\"age_years\"> ("
599
                    (item.date_of_birth
528
                        + $get_age(item.date_of_birth)
600
                        ? $date(item.date_of_birth) +
529
                        + " "
601
                          '<span class="age_years"> (' +
530
                        + __("years")
602
                          $get_age(item.date_of_birth) +
531
                        + ")</span>,"
603
                          " " +
532
                        : ""
604
                          __("years") +
533
                    ) + " "
605
                          ")</span>,"
534
                    + $format_address(item, { no_line_break: true, include_li: false }) + " "
606
                        : "") +
535
                    + (!singleBranchMode
607
                    " " +
536
                        ?
608
                    $format_address(item, {
537
                        "<span class=\"ac-library\">"
609
                        no_line_break: true,
538
                        + item.library.name.escapeHtml()
610
                        include_li: false,
539
                        + "</span>"
611
                    }) +
540
                        : "")
612
                    " " +
541
                    + "</small>"
613
                    (!singleBranchMode
542
                    + "</a>")
614
                        ? '<span class="ac-library">' +
543
                .appendTo(ul);
615
                          item.library.name.escapeHtml() +
544
        };
616
                          "</span>"
617
                        : "") +
618
                    "</small>" +
619
                    "</a>"
620
            )
621
            .appendTo(ul);
622
    });
545
}
623
}
546
624
547
function expandPatronSearchFields(search_fields) {
625
function expandPatronSearchFields(search_fields) {
548
    switch(search_fields) {
626
    switch (search_fields) {
549
        case 'standard':
627
        case "standard":
550
            return defaultPatronSearchFields;
628
            return defaultPatronSearchFields;
551
            break;
629
            break;
552
        case 'full_address':
630
        case "full_address":
553
            return 'streetnumber|streettype|address|address2|city|state|zipcode|country';
631
            return "streetnumber|streettype|address|address2|city|state|zipcode|country";
554
            break;
632
            break;
555
        case 'all_emails':
633
        case "all_emails":
556
            return 'email|emailpro|B_email';
634
            return "email|emailpro|B_email";
557
            break;
635
            break;
558
        case 'all_phones':
636
        case "all_phones":
559
            return 'phone|phonepro|B_phone|altcontactphone|mobile';
637
            return "phone|phonepro|B_phone|altcontactphone|mobile";
560
            break;
638
            break;
561
        default:
639
        default:
562
            return search_fields;
640
            return search_fields;
Lines 573-584 function expandPatronSearchFields(search_fields) { Link Here
573
 * - table_prefix: (String) table name to prefix the fields with, defaults to 'me'
651
 * - table_prefix: (String) table name to prefix the fields with, defaults to 'me'
574
 */
652
 */
575
function buildPatronSearchQuery(term, options) {
653
function buildPatronSearchQuery(term, options) {
576
577
    let q = [];
654
    let q = [];
578
    let table_prefix;
655
    let table_prefix;
579
    let leading_wildcard;
656
    let leading_wildcard;
580
    let search_fields = [];
657
    let search_fields = [];
581
    let patterns = term.split(/[\s,]+/).filter(function (s) { return s.length });
658
    let patterns = term.split(/[\s,]+/).filter(function (s) {
659
        return s.length;
660
    });
582
661
583
    // Bail if no patterns
662
    // Bail if no patterns
584
    if (patterns.length == 0) {
663
    if (patterns.length == 0) {
Lines 586-663 function buildPatronSearchQuery(term, options) { Link Here
586
    }
665
    }
587
666
588
    // Table prefix: If table_prefix options exists, use that
667
    // Table prefix: If table_prefix options exists, use that
589
    if (typeof options !== 'undefined' && options.table_prefix) {
668
    if (typeof options !== "undefined" && options.table_prefix) {
590
        table_prefix = options.table_prefix;
669
        table_prefix = options.table_prefix;
591
    // If not, default to 'me'
670
        // If not, default to 'me'
592
    } else {
671
    } else {
593
        table_prefix = 'me';
672
        table_prefix = "me";
594
    }
673
    }
595
674
596
    // Leading wildcard: If search_type option exists, use that
675
    // Leading wildcard: If search_type option exists, use that
597
    if (typeof options !== 'undefined' && options.search_type) {
676
    if (typeof options !== "undefined" && options.search_type) {
598
        leading_wildcard = options.search_type === "contains" ? '%' : '';
677
        leading_wildcard = options.search_type === "contains" ? "%" : "";
599
    // If not, use DefaultPatronSearchMethod system preference instead
678
        // If not, use DefaultPatronSearchMethod system preference instead
600
    } else {
679
    } else {
601
        leading_wildcard = defaultPatronSearchMethod === 'contains' ? '%' : '';
680
        leading_wildcard = defaultPatronSearchMethod === "contains" ? "%" : "";
602
    }
681
    }
603
682
604
    let searched_attribute_fields = [];
683
    let searched_attribute_fields = [];
605
    // Search fields: If search_fields option exists, we use that
684
    // Search fields: If search_fields option exists, we use that
606
    if (typeof options !== 'undefined' && options.search_fields) {
685
    if (typeof options !== "undefined" && options.search_fields) {
607
        expand_fields = expandPatronSearchFields(options.search_fields);
686
        expand_fields = expandPatronSearchFields(options.search_fields);
608
        expand_fields.split('\|').forEach(function (field, i) {
687
        expand_fields.split("|").forEach(function (field, i) {
609
            if( field.startsWith('_ATTR_') ){
688
            if (field.startsWith("_ATTR_")) {
610
                let attr_field = field.replace("_ATTR_","");
689
                let attr_field = field.replace("_ATTR_", "");
611
                searched_attribute_fields.push( attr_field );
690
                searched_attribute_fields.push(attr_field);
612
            } else {
691
            } else {
613
                search_fields.push( field );
692
                search_fields.push(field);
614
            }
693
            }
615
        });
694
        });
616
    // If not, we use DefaultPatronSearchFields system preference instead
695
        // If not, we use DefaultPatronSearchFields system preference instead
617
    } else {
696
    } else {
618
        search_fields = defaultPatronSearchFields.split('\|');
697
        search_fields = defaultPatronSearchFields.split("|");
619
    }
698
    }
620
699
621
    // Add each pattern for each search field
700
    // Add each pattern for each search field
622
    let pattern_subquery_and = [];
701
    let pattern_subquery_and = [];
623
    patterns.forEach(function (pattern, i) {
702
    patterns.forEach(function (pattern, i) {
624
            let pattern_subquery_or = [];
703
        let pattern_subquery_or = [];
625
            search_fields.forEach(function (field, i) {
704
        search_fields.forEach(function (field, i) {
626
                pattern_subquery_or.push(
705
            pattern_subquery_or.push({
627
                    { [table_prefix + "." + field]: { 'like': leading_wildcard + pattern + '%' } }
706
                [table_prefix + "." + field]: {
628
                );
707
                    like: leading_wildcard + pattern + "%",
629
                if (field == 'dateofbirth') {
708
                },
630
                    try {
631
                        let d = $date_to_rfc3339(pattern);
632
                        pattern_subquery_or.push({ [table_prefix + "." + field]: d });
633
                    } catch {
634
                        // Hide the warning if the date is not correct
635
                    }
636
                }
637
            });
709
            });
638
            pattern_subquery_and.push(pattern_subquery_or);
710
            if (field == "dateofbirth") {
711
                try {
712
                    let d = $date_to_rfc3339(pattern);
713
                    pattern_subquery_or.push({
714
                        [table_prefix + "." + field]: d,
715
                    });
716
                } catch {
717
                    // Hide the warning if the date is not correct
718
                }
719
            }
639
        });
720
        });
721
        pattern_subquery_and.push(pattern_subquery_or);
722
    });
640
    q.push({ "-and": pattern_subquery_and });
723
    q.push({ "-and": pattern_subquery_and });
641
724
642
643
    // Add full search term for each search field
725
    // Add full search term for each search field
644
    let term_subquery_or = [];
726
    let term_subquery_or = [];
645
    search_fields.forEach(function (field, i) {
727
    search_fields.forEach(function (field, i) {
646
        term_subquery_or.push(
728
        term_subquery_or.push({
647
            { [table_prefix + "." + field]: { 'like': leading_wildcard + term + '%' } }
729
            [table_prefix + "." + field]: {
648
        );
730
                like: leading_wildcard + term + "%",
731
            },
732
        });
649
    });
733
    });
650
    q.push({ "-or": term_subquery_or });
734
    q.push({ "-or": term_subquery_or });
651
735
652
    // Add each pattern for each extended patron attributes
736
    // Add each pattern for each extended patron attributes
653
    if ( typeof options !== 'undefined' && ( (options.search_fields == 'standard' && options.extended_attribute_types) || ( searched_attribute_fields.length > 0 ) ) && extendedPatronAttributes) {
737
    if (
654
        extended_attribute_codes_to_search = (searched_attribute_fields.length > 0) ? searched_attribute_fields : options.extended_attribute_types;
738
        typeof options !== "undefined" &&
739
        ((options.search_fields == "standard" &&
740
            options.extended_attribute_types) ||
741
            searched_attribute_fields.length > 0) &&
742
        extendedPatronAttributes
743
    ) {
744
        extended_attribute_codes_to_search =
745
            searched_attribute_fields.length > 0
746
                ? searched_attribute_fields
747
                : options.extended_attribute_types;
655
        extended_attribute_subquery_and = [];
748
        extended_attribute_subquery_and = [];
656
        patterns.forEach(function (pattern, i) {
749
        patterns.forEach(function (pattern, i) {
657
            let extended_attribute_sub_or = [];
750
            let extended_attribute_sub_or = [];
658
            extended_attribute_sub_or.push({
751
            extended_attribute_sub_or.push({
659
                "extended_attributes.value": { "like": leading_wildcard + pattern + '%' },
752
                "extended_attributes.value": {
660
                "extended_attributes.code": extended_attribute_codes_to_search
753
                    like: leading_wildcard + pattern + "%",
754
                },
755
                "extended_attributes.code": extended_attribute_codes_to_search,
661
            });
756
            });
662
            extended_attribute_subquery_and.push(extended_attribute_sub_or);
757
            extended_attribute_subquery_and.push(extended_attribute_sub_or);
663
        });
758
        });
Lines 666-678 function buildPatronSearchQuery(term, options) { Link Here
666
    return q;
761
    return q;
667
}
762
}
668
763
669
function selectBsTabByHash( tabs_container_id ){
764
function selectBsTabByHash(tabs_container_id) {
670
    /* Check for location.hash in the page URL */
765
    /* Check for location.hash in the page URL */
671
    /* If present the location hash will be used to activate the correct tab */
766
    /* If present the location hash will be used to activate the correct tab */
672
    var hash = document.location.hash;
767
    var hash = document.location.hash;
673
    if( hash !== "" ){
768
    if (hash !== "") {
674
        $('#' + tabs_container_id + ' a[href="' + hash + '"]').tab('show');
769
        $("#" + tabs_container_id + ' a[href="' + hash + '"]').tab("show");
675
    } else {
770
    } else {
676
        $('#' + tabs_container_id + ' a:first').tab('show');
771
        $("#" + tabs_container_id + " a:first").tab("show");
677
    }
772
    }
678
}
773
}
679
- 

Return to bug 36490