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

(-)a/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js (-405 / +400 lines)
Lines 169-615 function addConsentDeleteHandler() { Link Here
169
    })
169
    })
170
}
170
}
171
171
172
$( document ).ready( function () {
172
$("table.preferences").dataTable($.extend(true, {}, dataTablesDefaults, {
173
173
    "dom":  't',
174
    $("table.preferences").dataTable($.extend(true, {}, dataTablesDefaults, {
174
    "columnDefs":  [
175
        "dom":  't',
175
        { "targets":  [ -1 ], "orderable":  false, "searchable":  false }
176
        "columnDefs":  [
176
    ],
177
            { "targets":  [ -1 ], "orderable":  false, "searchable":  false }
177
    "paging":  false
178
        ],
178
}));
179
        "paging":  false
179
180
    }));
180
$( '.prefs-tab' )
181
181
    .find( 'input.preference, textarea.preference' ).on('input', function () {
182
    $( '.prefs-tab' )
182
        if ( this.defaultValue === undefined || this.value != this.defaultValue ) mark_modified.call( this );
183
        .find( 'input.preference, textarea.preference' ).on('input', function () {
183
    } ).end()
184
            if ( this.defaultValue === undefined || this.value != this.defaultValue ) mark_modified.call( this );
184
    .find( 'select.preference' ).change( mark_modified );
185
        } ).end()
185
$('.preference-checkbox').change( function () {
186
        .find( 'select.preference' ).change( mark_modified );
186
    $('.preference-checkbox').addClass('modified');
187
    $('.preference-checkbox').change( function () {
187
    mark_modified.call(this);
188
        $('.preference-checkbox').addClass('modified');
188
} );
189
        mark_modified.call(this);
190
    } );
191
192
    $(".set_syspref").click(function() {
193
        var s = $(this).attr('data-syspref');
194
        var v = $(this).attr('data-value');
195
        // populate the input with the value in data-value
196
        $("#pref_"+s).val(v);
197
        // pass the DOM element to trigger "modified" to enable submit button
198
        mark_modified.call($("#pref_"+s)[0]);
199
        return false;
200
    });
201
189
202
    $(".sortable").each( (i, e) => {
190
$(".set_syspref").click(function() {
203
        Sortable.create(e, {
191
    var s = $(this).attr('data-syspref');
204
            animation: 150,
192
    var v = $(this).attr('data-value');
205
            onUpdate: function( e ){
193
    // populate the input with the value in data-value
206
                $(e.target).find('input:first').change();
194
    $("#pref_"+s).val(v);
207
            }
195
    // pass the DOM element to trigger "modified" to enable submit button
208
        });
196
    mark_modified.call($("#pref_"+s)[0]);
197
    return false;
198
});
199
200
$(".sortable").each( (i, e) => {
201
    Sortable.create(e, {
202
        animation: 150,
203
        onUpdate: function( e ){
204
            $(e.target).find('input:first').change();
205
        }
209
    });
206
    });
207
});
210
208
211
    $( '.prefs-tab .action .cancel' ).click( function () { KOHA.Preferences.Modified = false } );
209
$( '.prefs-tab .action .cancel' ).click( function () { KOHA.Preferences.Modified = false } );
212
210
213
    $( '.prefs-tab .save-all' ).prop('disabled', true).click( function () {
211
$( '.prefs-tab .save-all' ).prop('disabled', true).click( function () {
214
        KOHA.Preferences.Save( this.form );
212
    KOHA.Preferences.Save( this.form );
215
        return false;
213
    return false;
216
    });
214
});
217
215
218
    addExpandHandler();
216
addExpandHandler();
219
217
220
    addCollapseHandler();
218
addCollapseHandler();
221
219
222
    $("h3").attr("class", "expanded").attr("title", __("Collapse this section"));
220
$("h3").attr("class", "expanded").attr("title", __("Collapse this section"));
223
    var collapsible = $(".collapsed,.expanded");
221
var collapsible = $(".collapsed,.expanded");
224
222
225
    $(collapsible).on("click",function(){
223
$(collapsible).on("click",function(){
226
        var h3Id = $(this).attr("id");
224
    var h3Id = $(this).attr("id");
227
        var panel = $("#collapse_" + h3Id);
225
    var panel = $("#collapse_" + h3Id);
228
        if(panel.is(":visible")){
226
    if(panel.is(":visible")){
229
            $(this).addClass("collapsed").removeClass("expanded").attr("title", __("Expand this section") );
227
        $(this).addClass("collapsed").removeClass("expanded").attr("title", __("Expand this section") );
230
            panel.hide();
228
        panel.hide();
231
        } else {
229
    } else {
232
            $(this).addClass("expanded").removeClass("collapsed").attr("title", __("Collapse this section") );
230
        $(this).addClass("expanded").removeClass("collapsed").attr("title", __("Collapse this section") );
233
            panel.show();
231
        panel.show();
234
        }
232
    }
235
    });
233
});
234
235
$(".pref_sublink").on("click", function(){
236
    /* If the user clicks a sub-menu link in the sidebar,
237
       check to see if it is collapsed. If so, expand it */
238
    var href = $(this).attr("href");
239
    href = href.replace("#","");
240
    var panel = $("#collapse_" + href );
241
    if( panel.is(":hidden") ){
242
        $("#" + href).addClass("expanded").removeClass("collapsed").attr("title", __("Collapse this section") );
243
        panel.show();
244
    }
245
});
236
246
237
    $(".pref_sublink").on("click", function(){
247
if ( to_highlight ) {
238
        /* If the user clicks a sub-menu link in the sidebar,
248
    var words = to_highlight.split( ' ' );
239
           check to see if it is collapsed. If so, expand it */
249
    $( '.prefs-tab table' ).find( 'td, th' ).not( '.name-cell' ).each( function ( i, td ) {
240
        var href = $(this).attr("href");
250
        $.each( words, function ( i, word ) { $( td ).highlight( word ) } );
241
        href = href.replace("#","");
251
    } ).find( 'option, textarea' ).removeHighlight();
242
        var panel = $("#collapse_" + href );
252
}
243
        if( panel.is(":hidden") ){
244
            $("#" + href).addClass("expanded").removeClass("collapsed").attr("title", __("Collapse this section") );
245
            panel.show();
246
        }
247
    });
248
253
249
    if ( to_highlight ) {
254
if ( search_jumped ) {
250
        var words = to_highlight.split( ' ' );
255
    document.location.hash = "jumped";
251
        $( '.prefs-tab table' ).find( 'td, th' ).not( '.name-cell' ).each( function ( i, td ) {
256
}
252
            $.each( words, function ( i, word ) { $( td ).highlight( word ) } );
253
        } ).find( 'option, textarea' ).removeHighlight();
254
    }
255
257
256
    if ( search_jumped ) {
258
$("#pref_UpdateItemLocationOnCheckin, #pref_UpdateItemLocationOnCheckout").change(function(){
257
        document.location.hash = "jumped";
259
    var the_text = $(this).val();
260
    var alert_text = '';
261
    if (the_text.indexOf('_ALL_:') != -1) alert_text = __("Note: _ALL_ value will override all other values") + '\n';
262
    var split_text  =the_text.split("\n");
263
    var alert_issues = '';
264
    var issue_count = 0;
265
    var reg_check = /.*:\s.*/;
266
    for (var i=0; i < split_text.length; i++){
267
        if ( !split_text[i].match(reg_check) && split_text[i].length ) {
268
            alert_issues+=split_text[i]+"\n";
269
            issue_count++;
270
        }
258
    }
271
    }
259
272
    if (issue_count) alert_text += "\n" + __("The following values are not formatted correctly:") + "\n" + alert_issues;
260
    $("#pref_UpdateItemLocationOnCheckin, #pref_UpdateItemLocationOnCheckout").change(function(){
273
    if ( alert_text.length )  alert(alert_text);
261
        var the_text = $(this).val();
274
});
262
        var alert_text = '';
275
263
        if (the_text.indexOf('_ALL_:') != -1) alert_text = __("Note: _ALL_ value will override all other values") + '\n';
276
$(".prefs-tab form").each(function () {
264
        var split_text  =the_text.split("\n");
277
    $(this).validate({
265
        var alert_issues = '';
278
        rules: { },
266
        var issue_count = 0;
279
        errorPlacement: function(error, element) {
267
        var reg_check = /.*:\s.*/;
280
            var placement = $(element).parent();
268
        for (var i=0; i < split_text.length; i++){
281
            if (placement) {
269
            if ( !split_text[i].match(reg_check) && split_text[i].length ) {
282
                $(placement).append(error)
270
                alert_issues+=split_text[i]+"\n";
283
            } else {
271
                issue_count++;
284
                error.insertAfter(element);
272
            }
285
            }
273
        }
286
        }
274
        if (issue_count) alert_text += "\n" + __("The following values are not formatted correctly:") + "\n" + alert_issues;
275
        if ( alert_text.length )  alert(alert_text);
276
    });
287
    });
288
});
277
289
278
    $(".prefs-tab form").each(function () {
290
$(".preference-email").each(function() {
279
        $(this).validate({
291
    $(this).rules("add", {
280
            rules: { },
292
        email: true
281
            errorPlacement: function(error, element) {
282
                var placement = $(element).parent();
283
                if (placement) {
284
                    $(placement).append(error)
285
                } else {
286
                    error.insertAfter(element);
287
                }
288
            }
289
        });
290
    });
293
    });
294
});
295
296
297
$(".modalselect").on("click", function(){
298
    var datasource = $(this).data("source");
299
    var exclusions = $(this).data("exclusions").split('|');
300
    var inclusions = $(this).data("inclusions").split('|');
301
    var required = $(this).data("required").split('|');
302
    var pref_name = this.id.replace(/pref_/, '');
303
    var pref_value = this.value;
304
    var prefs = pref_value.split("|");
305
306
    let data = db_columns[datasource];
307
    var items = [];
308
    var checked = "";
309
    var readonly = "";
310
    var disabled = "";
311
    var style = "";
312
    $.each( Object.keys(data).sort(), function( i, key ){
313
        if( prefs.indexOf( key ) >= 0 ){
314
            checked = ' checked="checked" ';
315
        } else {
316
            checked = "";
317
        }
318
        if( required.indexOf( key ) >= 0 ){
319
            style = "required";
320
            checked  = ' checked="checked" ';
321
        } else if( exclusions.indexOf( key ) >= 0 ){
322
            style = "disabled";
323
            disabled = ' disabled="disabled" ';
324
            checked  = "";
325
        } else if( inclusions.indexOf( key ) >= 0 ){
326
            style = "disabled";
327
            disabled = ' disabled="disabled" ';
328
            checked  = ' checked="checked" ';
329
        } else {
330
            style = "";
331
            disabled = "";
332
        }
291
333
292
    $(".preference-email").each(function() {
334
        items.push('<label class="' + style +'"><input class="dbcolumn_selection" type="checkbox" id="' + key + '"' + checked + disabled + ' name="pref" value="' + key + '" /> ' + data[key]+ ' (' + key + ')</label>');
293
        $(this).rules("add", {
294
            email: true
295
        });
296
    });
335
    });
297
336
    $("<div/>", {
298
337
        "class": "columns-2",
299
    $(".modalselect").on("click", function(){
338
        html: items.join("")
300
        var datasource = $(this).data("source");
339
    }).appendTo("#prefModalBody");
301
        var exclusions = $(this).data("exclusions").split('|');
340
302
        var inclusions = $(this).data("inclusions").split('|');
341
    $("#saveModalPrefs").data("target", this.id );
303
        var required = $(this).data("required").split('|');
342
    $("#saveModalPrefs").data("type", "modalselect" );
304
        var pref_name = this.id.replace(/pref_/, '');
343
    $("#prefModalLabel").text( pref_name );
305
        var pref_value = this.value;
344
    $("#prefModal").modal("show");
306
        var prefs = pref_value.split("|");
345
});
307
346
308
        let data = db_columns[datasource];
347
// Initialise the content of our modal, using the function
309
        var items = [];
348
// specified in the data-initiator attribute
310
        var checked = "";
349
$('.modaljs').on('click', function () {
311
        var readonly = "";
350
    const init = $(this).data('initiator');
312
        var disabled = "";
351
    if (init) {
313
        var style = "";
352
        window[init](this);
314
        $.each( Object.keys(data).sort(), function( i, key ){
315
            if( prefs.indexOf( key ) >= 0 ){
316
                checked = ' checked="checked" ';
317
            } else {
318
                checked = "";
319
            }
320
            if( required.indexOf( key ) >= 0 ){
321
                style = "required";
322
                checked  = ' checked="checked" ';
323
            } else if( exclusions.indexOf( key ) >= 0 ){
324
                style = "disabled";
325
                disabled = ' disabled="disabled" ';
326
                checked  = "";
327
            } else if( inclusions.indexOf( key ) >= 0 ){
328
                style = "disabled";
329
                disabled = ' disabled="disabled" ';
330
                checked  = ' checked="checked" ';
331
            } else {
332
                style = "";
333
                disabled = "";
334
            }
335
336
            items.push('<label class="' + style +'"><input class="dbcolumn_selection" type="checkbox" id="' + key + '"' + checked + disabled + ' name="pref" value="' + key + '" /> ' + data[key]+ ' (' + key + ')</label>');
337
        });
338
        $("<div/>", {
339
            "class": "columns-2",
340
            html: items.join("")
341
        }).appendTo("#prefModalBody");
342
343
        $("#saveModalPrefs").data("target", this.id );
344
        $("#saveModalPrefs").data("type", "modalselect" );
345
        $("#prefModalLabel").text( pref_name );
346
        $("#prefModal").modal("show");
353
        $("#prefModal").modal("show");
347
    });
354
    }
348
355
});
349
    // Initialise the content of our modal, using the function
356
350
    // specified in the data-initiator attribute
357
// Initialise the content of our modal, if we are dealing
351
    $('.modaljs').on('click', function () {
358
// with a modalselect modal
352
        const init = $(this).data('initiator');
359
function prepareModalSelect(formfieldid) {
353
        if (init) {
360
    var prefs = [];
354
            window[init](this);
361
    $("#prefModal input[type='checkbox']").each(function(){
355
            $("#prefModal").modal("show");
362
        if( $(this).prop("checked") ){
363
            prefs.push( this.value );
356
        }
364
        }
357
    });
365
    });
366
    return prefs.join("|");
367
}
358
368
359
    // Initialise the content of our modal, if we are dealing
369
// Return a checkbox with an appropriate checked state
360
    // with a modalselect modal
370
function checkBox(id, className, state) {
361
    function prepareModalSelect(formfieldid) {
371
    return state ?
362
        var prefs = [];
372
        '<input id="' + id + '" type="checkbox" class="' + className + '" checked>' :
363
        $("#prefModal input[type='checkbox']").each(function(){
373
        '<input id="' + id + '" type="checkbox" class="' + className + '">';
364
            if( $(this).prop("checked") ){
374
}
365
                prefs.push( this.value );
366
            }
367
        });
368
        return prefs.join("|");
369
    }
370
371
    // Return a checkbox with an appropriate checked state
372
    function checkBox(id, className, state) {
373
        return state ?
374
            '<input id="' + id + '" type="checkbox" class="' + className + '" checked>' :
375
            '<input id="' + id + '" type="checkbox" class="' + className + '">';
376
    }
377
378
    // Create a cookieConsentedJS item, correctly populated
379
    function createCookieConsentedJSItem(item, idx) {
380
        const id = 'CookieConsentedJS_' + idx;
381
        const code = item.code && item.code.length > 0 ? atob(item.code) : '';
382
        const itemId = item.id && item.id.length > 0 ? item.id : '';
383
        return '<div id="' + id + '" class="cookieConsentedJSItem" data-id="' + itemId + '">' +
384
               '    <div class="consentRow">' +
385
               '        <div class="consentItem">' +
386
               '            <label class="required" for="name_' + id + '">' + __('Name') + ':</label>' +
387
               '            <input id="name_' + id + '" class="metaName" type="text" value="' + item.name + '"><span class="required">' + __('Required') + '</span>' +
388
               '        </div >' +
389
               '        <div class="consentItem">' +
390
               '            <label class="required" for="description_' + id + '">' + __('Description') + ':</label>' +
391
               '            <input id="description_' + id + '" class="metaDescription" type="text" value="' + item.description + '"><span class="required">' + __('Required') + '</span>' +
392
               '        </div>' +
393
               '        <div class="consentItem">' +
394
               '            <label for="opacConsent_' + id + '">' + __('Requires consent in OPAC') + ':</label>' +
395
                            checkBox('opacConsent_' + id, 'opacConsent', item.opacConsent) +
396
               '        </div>' +
397
               '        <div class="consentItem">' +
398
               '            <label for="staffConsent_' + id + '">' + __('Requires consent in staff interface') + ':</label>' +
399
                            checkBox('staffConsent_' + id, 'staffConsent', item.staffConsent) +
400
               '        </div >' +
401
               '        <div class="consentItem">' +
402
               '            <label for="matchPattern_' + id + '">' + __('String used to identify cookie name') + ':</label>' +
403
               '            <input id="matchPattern_' + id + '" class="metaMatchPattern" type="text" value="' + item.matchPattern + '"><span class="required">' + __('Required') + '</span>' +
404
               '        </div >' +
405
               '        <div class="consentItem">' +
406
               '            <label for="cookieDomain' + id + '">' + __('Cookie domain') + ':</label>' +
407
               '            <input id="cookieDomain' + id + '" class="metaCookieDomain" type="text" value="' + item.cookieDomain + '"><span class="required">' + __('Required') + '</span>' +
408
               '        </div >' +
409
               '        <div class="consentItem">' +
410
               '            <label for="cookiePath' + id + '">' + __('Cookie path') + ':</label>' +
411
               '            <input id="cookiePath' + id + '" class="metaCookiePath" type="text" value="' + item.cookiePath + '"><span class="required">' + __('Required') + '</span>' +
412
               '        </div >' +
413
               '    </div >' +
414
               '    <div class="consentRow codeRow">' +
415
               '        <textarea style="display:none;" id="pref_' + id + '" class="preference preference-code codemirror" rows="10" cols="40">' + code + '</textarea>' +
416
               '        <div>' +
417
               '            <a id="expand_' + id + '" class="expand-textarea" data-target="' + id + '" data-syntax="javascript" href="#">' + __('Expand') + '</a>' +
418
               '            <a id="collapse_' + id + '" class="collapse-textarea" data-target="' + id + '" data-syntax="javascript" href="#" style="display:none">' + __('Collapse') + '</a>' +
419
               '        </div >' +
420
               '    </div>' +
421
               '    <a class="consentDelete" data-target="' + id + '" href="#">' + __('Delete') + '</a>' +
422
               '</div > ';
423
    }
424
375
425
    // Return the markup for all cookieConsentedJS items concatenated
376
// Create a cookieConsentedJS item, correctly populated
426
    function populateConsentMarkup(items) {
377
function createCookieConsentedJSItem(item, idx) {
427
        return items.reduce(function (acc, current, idx) {
378
    const id = 'CookieConsentedJS_' + idx;
428
            return acc + createCookieConsentedJSItem(current, idx);
379
    const code = item.code && item.code.length > 0 ? atob(item.code) : '';
429
        }, '');
380
    const itemId = item.id && item.id.length > 0 ? item.id : '';
430
    }
381
    return '<div id="' + id + '" class="cookieConsentedJSItem" data-id="' + itemId + '">' +
382
           '    <div class="consentRow">' +
383
           '        <div class="consentItem">' +
384
           '            <label class="required" for="name_' + id + '">' + __('Name') + ':</label>' +
385
           '            <input id="name_' + id + '" class="metaName" type="text" value="' + item.name + '"><span class="required">' + __('Required') + '</span>' +
386
           '        </div >' +
387
           '        <div class="consentItem">' +
388
           '            <label class="required" for="description_' + id + '">' + __('Description') + ':</label>' +
389
           '            <input id="description_' + id + '" class="metaDescription" type="text" value="' + item.description + '"><span class="required">' + __('Required') + '</span>' +
390
           '        </div>' +
391
           '        <div class="consentItem">' +
392
           '            <label for="opacConsent_' + id + '">' + __('Requires consent in OPAC') + ':</label>' +
393
                        checkBox('opacConsent_' + id, 'opacConsent', item.opacConsent) +
394
           '        </div>' +
395
           '        <div class="consentItem">' +
396
           '            <label for="staffConsent_' + id + '">' + __('Requires consent in staff interface') + ':</label>' +
397
                        checkBox('staffConsent_' + id, 'staffConsent', item.staffConsent) +
398
           '        </div >' +
399
           '        <div class="consentItem">' +
400
           '            <label for="matchPattern_' + id + '">' + __('String used to identify cookie name') + ':</label>' +
401
           '            <input id="matchPattern_' + id + '" class="metaMatchPattern" type="text" value="' + item.matchPattern + '"><span class="required">' + __('Required') + '</span>' +
402
           '        </div >' +
403
           '        <div class="consentItem">' +
404
           '            <label for="cookieDomain' + id + '">' + __('Cookie domain') + ':</label>' +
405
           '            <input id="cookieDomain' + id + '" class="metaCookieDomain" type="text" value="' + item.cookieDomain + '"><span class="required">' + __('Required') + '</span>' +
406
           '        </div >' +
407
           '        <div class="consentItem">' +
408
           '            <label for="cookiePath' + id + '">' + __('Cookie path') + ':</label>' +
409
           '            <input id="cookiePath' + id + '" class="metaCookiePath" type="text" value="' + item.cookiePath + '"><span class="required">' + __('Required') + '</span>' +
410
           '        </div >' +
411
           '    </div >' +
412
           '    <div class="consentRow codeRow">' +
413
           '        <textarea style="display:none;" id="pref_' + id + '" class="preference preference-code codemirror" rows="10" cols="40">' + code + '</textarea>' +
414
           '        <div>' +
415
           '            <a id="expand_' + id + '" class="expand-textarea" data-target="' + id + '" data-syntax="javascript" href="#">' + __('Expand') + '</a>' +
416
           '            <a id="collapse_' + id + '" class="collapse-textarea" data-target="' + id + '" data-syntax="javascript" href="#" style="display:none">' + __('Collapse') + '</a>' +
417
           '        </div >' +
418
           '    </div>' +
419
           '    <a class="consentDelete" data-target="' + id + '" href="#">' + __('Delete') + '</a>' +
420
           '</div > ';
421
}
431
422
432
    // Return the markup for a validation warning
423
// Return the markup for all cookieConsentedJS items concatenated
433
    function populateValidationWarning() {
424
function populateConsentMarkup(items) {
434
        return '<div id="cookieConsentedJSWarning" class="error" style="display:none;">' + __('You must complete all fields') + '</div>';
425
    return items.reduce(function (acc, current, idx) {
435
    }
426
        return acc + createCookieConsentedJSItem(current, idx);
427
    }, '');
428
}
436
429
437
    // Return a new, empty consent item
430
// Return the markup for a validation warning
438
    function emptyConsentItem() {
431
function populateValidationWarning() {
439
        return {
432
    return '<div id="cookieConsentedJSWarning" class="error" style="display:none;">' + __('You must complete all fields') + '</div>';
440
            name: '',
433
}
441
            description: '',
442
            matchPattern: '',
443
            cookieDomain: '',
444
            cookiePath: '',
445
            code: '',
446
            opacConsent: false,
447
            staffConsent: false
448
        };
449
    }
450
434
451
    // Add the handler for a new empty consent item
435
// Return a new, empty consent item
452
    function addNewHandler() {
436
function emptyConsentItem() {
453
        $("#cookieConsentedJSAddNew").on("click", function (e) {
437
    return {
454
            e.preventDefault();
438
        name: '',
455
            const currentLen = $('.cookieConsentedJSItem').length;
439
        description: '',
456
            const newItem = emptyConsentItem();
440
        matchPattern: '',
457
            const markup = createCookieConsentedJSItem(newItem, currentLen);
441
        cookieDomain: '',
458
            $('#prefModal .modal-body #cookieConsentedJSItems').append($(markup));
442
        cookiePath: '',
459
            addExpandHandler();
443
        code: '',
460
            addCollapseHandler();
444
        opacConsent: false,
461
            addConsentDeleteHandler();
445
        staffConsent: false
462
        });
446
    };
463
    }
447
}
464
448
465
    // Populate the cookieConsentedJS modal, we also initialise any
449
// Add the handler for a new empty consent item
466
    // event handlers that are required. This function is added
450
function addNewHandler() {
467
    // to the window object so we can call it if we are passed it's name
451
    $("#cookieConsentedJSAddNew").on("click", function (e) {
468
    // as a data-initiator attribute
452
        e.preventDefault();
469
    // (e.g.)
453
        const currentLen = $('.cookieConsentedJSItem').length;
470
    // const f = 'populateCookieConsentedJS';
454
        const newItem = emptyConsentItem();
471
    // window[f]();
455
        const markup = createCookieConsentedJSItem(newItem, currentLen);
472
    window.populateCookieConsentedJS = function(el) {
456
        $('#prefModal .modal-body #cookieConsentedJSItems').append($(markup));
473
        let items = [];
474
        let decoded = '';
475
        if (el.value && el.value.length > 0) {
476
            try {
477
                decoded = atob(el.value);
478
            } catch (err) {
479
                throw (__(
480
                    'Unable to Base64 decode value stored in CookieConsentedJS syspref: ' +
481
                    err.message
482
                ));
483
            }
484
            try {
485
                items = JSON.parse(decoded);
486
            } catch (err) {
487
                throw (__(
488
                    'Unable to JSON parse decoded value stored in CookieConsentedJS syspref: ' +
489
                    err.message
490
                ));
491
            }
492
        }
493
        const markup = populateConsentMarkup(items);
494
        const validationWarning = populateValidationWarning();
495
        const pref_name = el.id.replace(/pref_/, '');
496
        $('#saveModalPrefs').data('target', el.id);
497
        $('#prefModalLabel').text( pref_name );
498
        $('#prefModal .modal-body').html($('<div id="cookieConsentedJSItems">' + validationWarning + markup + '</div><div><a href="#" id="cookieConsentedJSAddNew">' + __('Add new code') + '</a></div>'));
499
        addExpandHandler();
457
        addExpandHandler();
500
        addCollapseHandler();
458
        addCollapseHandler();
501
        addNewHandler();
502
        addConsentDeleteHandler();
459
        addConsentDeleteHandler();
503
    }
460
    });
461
}
504
462
505
    // Prepare the data in the UI for sending back as a syspref.
463
// Populate the cookieConsentedJS modal, we also initialise any
506
    // We validate that everything is what we expect. This function is added
464
// event handlers that are required. This function is added
507
    // to the window object so we can call it if we are passed it's name
465
// to the window object so we can call it if we are passed it's name
508
    // as a data-initiator attribute
466
// as a data-initiator attribute
509
    // e.g.
467
// (e.g.)
510
    // const f = 'prepareCookieConsentedJS';
468
// const f = 'populateCookieConsentedJS';
511
    // window[f]();
469
// window[f]();
512
    window.prepareCookieConsentedJS = function () {
470
window.populateCookieConsentedJS = function(el) {
513
        const items = $('.cookieConsentedJSItem');
471
    let items = [];
514
        const invalid = [];
472
    let decoded = '';
515
        const valid = [];
473
    if (el.value && el.value.length > 0) {
516
        items.each(function () {
474
        try {
517
            const id = $(this).data('id').length > 0 ?
475
            decoded = atob(el.value);
518
                $(this).data('id') :
476
        } catch (err) {
519
                '_' + Math.random().toString(36).substr(2, 9);
477
            throw (__(
520
            const name = $(this).find('.metaName').val();
478
                'Unable to Base64 decode value stored in CookieConsentedJS syspref: ' +
521
            const desc = $(this).find('.metaDescription').val();
479
                err.message
522
            const matchPattern = $(this).find('.metaMatchPattern').val();
480
            ));
523
            const cookieDomain = $(this).find('.metaCookieDomain').val();
524
            const cookiePath = $(this).find('.metaCookiePath').val();
525
            const opacConsent = $(this).find('.opacConsent').is(':checked')
526
            const staffConsent = $(this).find('.staffConsent').is(':checked');
527
            const code = $(this).find('.preference-code').val();
528
            // If the name, description, match pattern code are empty, then they've
529
            // added a new entry, but not filled it in, we can skip it
530
            if (
531
                name.length === 0 &&
532
                desc.length === 0 &&
533
                matchPattern.length === 0 &&
534
                cookieDomain.length === 0 &&
535
                cookiePath.length === 0 &&
536
                code.length === 0
537
            ) {
538
                return;
539
            }
540
            // They've filled in at least some info
541
            if (
542
                (name.length === 0) ||
543
                (desc.length === 0) ||
544
                (matchPattern.length === 0) ||
545
                (cookiePath.length === 0) ||
546
                (code.length === 0)
547
            ) {
548
                invalid.push(this);
549
            } else {
550
                const obj = {
551
                    id: id,
552
                    name: name,
553
                    description: desc,
554
                    matchPattern: matchPattern,
555
                    cookieDomain: cookieDomain,
556
                    cookiePath: cookiePath,
557
                    opacConsent: opacConsent,
558
                    staffConsent: staffConsent,
559
                    code: btoa(code)
560
                }
561
                valid.push(obj);
562
            }
563
        });
564
        // We failed validation
565
        if (invalid.length > 0) {
566
            $('#cookieConsentedJSWarning').show();
567
            return false;
568
        }
481
        }
569
        $('#cookieConsentedJSWarning').hide();
482
        try {
570
        if (valid.length === 0) {
483
            items = JSON.parse(decoded);
571
            return '';
484
        } catch (err) {
485
            throw (__(
486
                'Unable to JSON parse decoded value stored in CookieConsentedJS syspref: ' +
487
                err.message
488
            ));
572
        }
489
        }
573
        const json = JSON.stringify(valid);
574
        const base64 = btoa(json);
575
        return base64;
576
    }
490
    }
491
    const markup = populateConsentMarkup(items);
492
    const validationWarning = populateValidationWarning();
493
    const pref_name = el.id.replace(/pref_/, '');
494
    $('#saveModalPrefs').data('target', el.id);
495
    $('#prefModalLabel').text( pref_name );
496
    $('#prefModal .modal-body').html($('<div id="cookieConsentedJSItems">' + validationWarning + markup + '</div><div><a href="#" id="cookieConsentedJSAddNew">' + __('Add new code') + '</a></div>'));
497
    addExpandHandler();
498
    addCollapseHandler();
499
    addNewHandler();
500
    addConsentDeleteHandler();
501
}
577
502
578
    $("#saveModalPrefs").on("click", function(){
503
// Prepare the data in the UI for sending back as a syspref.
579
        var formfieldid = $("#" + $(this).data("target"));
504
// We validate that everything is what we expect. This function is added
580
        let finalString = "";
505
// to the window object so we can call it if we are passed it's name
581
        if ($(this).data("type") == "modalselect") {
506
// as a data-initiator attribute
582
            finalString = prepareModalSelect(formfieldid);
507
// e.g.
583
        } else {
508
// const f = 'prepareCookieConsentedJS';
584
            const processor = $(".modaljs").data("processor");
509
// window[f]();
585
            finalString = window[processor]();
510
window.prepareCookieConsentedJS = function () {
511
    const items = $('.cookieConsentedJSItem');
512
    const invalid = [];
513
    const valid = [];
514
    items.each(function () {
515
        const id = $(this).data('id').length > 0 ?
516
            $(this).data('id') :
517
            '_' + Math.random().toString(36).substr(2, 9);
518
        const name = $(this).find('.metaName').val();
519
        const desc = $(this).find('.metaDescription').val();
520
        const matchPattern = $(this).find('.metaMatchPattern').val();
521
        const cookieDomain = $(this).find('.metaCookieDomain').val();
522
        const cookiePath = $(this).find('.metaCookiePath').val();
523
        const opacConsent = $(this).find('.opacConsent').is(':checked')
524
        const staffConsent = $(this).find('.staffConsent').is(':checked');
525
        const code = $(this).find('.preference-code').val();
526
        // If the name, description, match pattern code are empty, then they've
527
        // added a new entry, but not filled it in, we can skip it
528
        if (
529
            name.length === 0 &&
530
            desc.length === 0 &&
531
            matchPattern.length === 0 &&
532
            cookieDomain.length === 0 &&
533
            cookiePath.length === 0 &&
534
            code.length === 0
535
        ) {
536
            return;
586
        }
537
        }
587
        // A processor can return false if any of the submitted
538
        // They've filled in at least some info
588
        // data has failed validation
539
        if (
589
        if (finalString !== false) {
540
            (name.length === 0) ||
590
            formfieldid.val(finalString).addClass("modified");
541
            (desc.length === 0) ||
591
            mark_modified.call( formfieldid );
542
            (matchPattern.length === 0) ||
592
            KOHA.Preferences.Save( formfieldid.closest("form") );
543
            (cookiePath.length === 0) ||
593
            $("#prefModal").modal("hide");
544
            (code.length === 0)
545
        ) {
546
            invalid.push(this);
547
        } else {
548
            const obj = {
549
                id: id,
550
                name: name,
551
                description: desc,
552
                matchPattern: matchPattern,
553
                cookieDomain: cookieDomain,
554
                cookiePath: cookiePath,
555
                opacConsent: opacConsent,
556
                staffConsent: staffConsent,
557
                code: btoa(code)
558
            }
559
            valid.push(obj);
594
        }
560
        }
595
    });
561
    });
562
    // We failed validation
563
    if (invalid.length > 0) {
564
        $('#cookieConsentedJSWarning').show();
565
        return false;
566
    }
567
    $('#cookieConsentedJSWarning').hide();
568
    if (valid.length === 0) {
569
        return '';
570
    }
571
    const json = JSON.stringify(valid);
572
    const base64 = btoa(json);
573
    return base64;
574
}
596
575
597
    $("#prefModal").on("hide.bs.modal", function(){
576
$("#saveModalPrefs").on("click", function(){
598
        $("#prefModalLabel,#prefModalBody").html("");
577
    var formfieldid = $("#" + $(this).data("target"));
599
        $("#saveModalPrefs").data("target", "" );
578
    let finalString = "";
600
    });
579
    if ($(this).data("type") == "modalselect") {
601
580
        finalString = prepareModalSelect(formfieldid);
602
    $("#select_all").on("click",function(e){
581
    } else {
603
        e.preventDefault();
582
        const processor = $(".modaljs").data("processor");
604
        $("label:not(.required) .dbcolumn_selection:not(:disabled)").prop("checked", true);
583
        finalString = window[processor]();
605
    });
584
    }
606
    $("#clear_all").on("click",function(e){
585
    // A processor can return false if any of the submitted
607
        e.preventDefault();
586
    // data has failed validation
608
        $("label:not(.required) .dbcolumn_selection").prop("checked", false);
587
    if (finalString !== false) {
609
    });
588
        formfieldid.val(finalString).addClass("modified");
610
589
        mark_modified.call( formfieldid );
611
    $("body").on("click", "label.required input.dbcolumn_selection", function(e){
590
        KOHA.Preferences.Save( formfieldid.closest("form") );
612
        e.preventDefault();
591
        $("#prefModal").modal("hide");
613
    });
592
    }
614
593
});
615
} );
594
595
$("#prefModal").on("hide.bs.modal", function(){
596
    $("#prefModalLabel,#prefModalBody").html("");
597
    $("#saveModalPrefs").data("target", "" );
598
});
599
600
$("#select_all").on("click",function(e){
601
    e.preventDefault();
602
    $("label:not(.required) .dbcolumn_selection:not(:disabled)").prop("checked", true);
603
});
604
$("#clear_all").on("click",function(e){
605
    e.preventDefault();
606
    $("label:not(.required) .dbcolumn_selection").prop("checked", false);
607
});
608
609
$("body").on("click", "label.required input.dbcolumn_selection", function(e){
610
    e.preventDefault();
611
});
616
- 

Return to bug 34655