From ab30078a7a30862ad55a2a36fe27b3d9cf4250dd Mon Sep 17 00:00:00 2001 From: Matt Blenkinsop Date: Thu, 25 May 2023 15:41:51 +0000 Subject: [PATCH] Bug 27378: Stop the codemirror editor from duplicating Previously, if the "Add new code button" was clicked in the CookieConsentedJS editor, the original entry would have duplicated CodeMirror editors. This was exponential, i.e adding two new lines would result in three codemirror editors appearing on the first entry, two on the second and so on. The click event was not being applied properly and was being applied to every element with the .expand-textarea class, rather than specifically the new elements being created. The addExpandHandler function now loops through each element individually and decides whether to apply the click event handler. Signed-off-by: Sam Lau --- .../prog/js/pages/preferences.js | 145 ++++++++++-------- 1 file changed, 78 insertions(+), 67 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js b/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js index 0d5972ddb1..6bde33bba4 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js +++ b/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js @@ -67,58 +67,69 @@ window.onbeforeunload = function () { // Add event handlers to any elements with .expand-textarea classes // this allows the CodeMirror widget to be displayed function addExpandHandler() { - // Don't duplicate click event handlers - const ev = $._data($('.expand-textarea'), 'events'); - if (ev && ev.click) { - return; - } - $(".expand-textarea").on("click", function (e) { - e.preventDefault(); - $(this).hide(); - var target = $(this).data("target"); - var syntax = $(this).data("syntax"); - $("#collapse_" + target).show(); - if (syntax) { - var editor = CodeMirror.fromTextArea(document.getElementById("pref_" + target), { - lineNumbers: true, - mode: syntax, - lineWrapping: true, - viewportMargin: Infinity, - gutters: ["CodeMirror-lint-markers"], - lint: true - }); - editor.on("change", function () { - mark_modified.call($("#pref_" + target)[0]); - }); - editor.on("blur", function () { - editor.save(); - }); - } else { - $("#pref_" + target).show(); + const textAreas = $('.expand-textarea').map(function() { + return this + }).get(); + textAreas.forEach((expandTextArea) => { + // Don't duplicate click event handlers + const ev = $._data($(expandTextArea).get(0), 'events'); + if (ev && ev.click) { + return; } - }); + // Add the click event + $(expandTextArea).on("click", function (e) { + e.preventDefault(); + $(this).hide(); + var target = $(this).data("target"); + var syntax = $(this).data("syntax"); + $("#collapse_" + target).show(); + if (syntax) { + var editor = CodeMirror.fromTextArea(document.getElementById("pref_" + target), { + lineNumbers: true, + mode: syntax, + lineWrapping: true, + viewportMargin: Infinity, + gutters: ["CodeMirror-lint-markers"], + lint: true + }); + editor.on("change", function () { + mark_modified.call($("#pref_" + target)[0]); + }); + editor.on("blur", function () { + editor.save(); + }); + } else { + $("#pref_" + target).show(); + } + }); + }) } // Add event handlers to any elements with .collapse-textarea classes // this allows the hiding of the CodeMirror widget function addCollapseHandler() { - // Don't duplicate click event handlers - const ev = $._data($('.collapse-textarea'), 'events'); - if (ev && ev.click) { - return; - } - $(".collapse-textarea").on("click", function (e) { - e.preventDefault(); - $(this).hide(); - var target = $(this).data("target"); - var syntax = $(this).data("syntax"); - $("#expand_" + target).show(); - if (syntax) { - var editor = $("#pref_" + target).next(".CodeMirror")[0].CodeMirror; - editor.toTextArea(); + const textAreas = $('.collapse-textarea').map(function() { + return this + }).get(); + textAreas.forEach((collapseTextArea) => { + // Don't duplicate click event handlers + const ev = $._data($(collapseTextArea).get(0), 'events'); + if (ev && ev.click) { + return; } - $("#pref_" + target).hide(); - }); + $(collapseTextArea).on("click", function (e) { + e.preventDefault(); + $(this).hide(); + var target = $(this).data("target"); + var syntax = $(this).data("syntax"); + $("#expand_" + target).show(); + if (syntax) { + var editor = $("#pref_" + target).next(".CodeMirror")[0].CodeMirror; + editor.toTextArea(); + } + $("#pref_" + target).hide(); + }); + }) } // Add a handler for any consent delete links @@ -335,12 +346,12 @@ $( document ).ready( function () { ''; } - // Create a consentJS item, correctly populated - function createConsentJSItem(item, idx) { - const id = 'ConsentJS_' + idx; + // Create a cookieConsentedJS item, correctly populated + function createCookieConsentedJSItem(item, idx) { + const id = 'CookieConsentedJS_' + idx; const code = item.code && item.code.length > 0 ? atob(item.code) : ''; const itemId = item.id && item.id.length > 0 ? item.id : ''; - return '
' + + return '
' + '
' + '
' + ' ' + @@ -382,16 +393,16 @@ $( document ).ready( function () { '
'; } - // Return the markup for all consentJS items concatenated + // Return the markup for all cookieConsentedJS items concatenated function populateConsentMarkup(items) { return items.reduce(function (acc, current, idx) { - return acc + createConsentJSItem(current, idx); + return acc + createCookieConsentedJSItem(current, idx); }, ''); } // Return the markup for a validation warning function populateValidationWarning() { - return ''; + return ''; } // Return a new, empty consent item @@ -410,26 +421,26 @@ $( document ).ready( function () { // Add the handler for a new empty consent item function addNewHandler() { - $("#consentJSAddNew").on("click", function (e) { + $("#cookieConsentedJSAddNew").on("click", function (e) { e.preventDefault(); - const currentLen = $('.consentJSItem').length; + const currentLen = $('.cookieConsentedJSItem').length; const newItem = emptyConsentItem(); - const markup = createConsentJSItem(newItem, currentLen); - $('#prefModal .modal-body #consentJSItems').append($(markup)); + const markup = createCookieConsentedJSItem(newItem, currentLen); + $('#prefModal .modal-body #cookieConsentedJSItems').append($(markup)); addExpandHandler(); addCollapseHandler(); addConsentDeleteHandler(); }); } - // Populate the consentJS modal, we also initialise any + // Populate the cookieConsentedJS modal, we also initialise any // event handlers that are required. This function is added // to the window object so we can call it if we are passed it's name // as a data-initiator attribute // (e.g.) - // const f = 'populateConsentJS'; + // const f = 'populateCookieConsentedJS'; // window[f](); - window.populateConsentJS = function(el) { + window.populateCookieConsentedJS = function(el) { let items = []; let decoded = ''; if (el.value && el.value.length > 0) { @@ -437,7 +448,7 @@ $( document ).ready( function () { decoded = atob(el.value); } catch (err) { throw (__( - 'Unable to Base64 decode value stored in ConsentJS syspref: ' + + 'Unable to Base64 decode value stored in CookieConsentedJS syspref: ' + err.message )); } @@ -445,7 +456,7 @@ $( document ).ready( function () { items = JSON.parse(decoded); } catch (err) { throw (__( - 'Unable to JSON parse decoded value stored in ConsentJS syspref: ' + + 'Unable to JSON parse decoded value stored in CookieConsentedJS syspref: ' + err.message )); } @@ -455,7 +466,7 @@ $( document ).ready( function () { const pref_name = el.id.replace(/pref_/, ''); $('#saveModalPrefs').data('target', el.id); $('#prefModalLabel').text( pref_name ); - $('#prefModal .modal-body').html($('
' + validationWarning + markup + '
')); + $('#prefModal .modal-body').html($('
' + validationWarning + markup + '
')); addExpandHandler(); addCollapseHandler(); addNewHandler(); @@ -467,10 +478,10 @@ $( document ).ready( function () { // to the window object so we can call it if we are passed it's name // as a data-initiator attribute // e.g. - // const f = 'prepareConsentJS'; + // const f = 'prepareCookieConsentedJS'; // window[f](); - window.prepareConsentJS = function () { - const items = $('.consentJSItem'); + window.prepareCookieConsentedJS = function () { + const items = $('.cookieConsentedJSItem'); const invalid = []; const valid = []; items.each(function () { @@ -523,10 +534,10 @@ $( document ).ready( function () { }); // We failed validation if (invalid.length > 0) { - $('#consentJSWarning').show(); + $('#cookieConsentedJSWarning').show(); return false; } - $('#consentJSWarning').hide(); + $('#cookieConsentedJSWarning').hide(); if (valid.length === 0) { return ''; } -- 2.30.2