diff --git a/.editorconfig b/.editorconfig index d4eb1a005b..c8c8d8fef7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,7 +10,7 @@ indent_style = space insert_final_newline = true trim_trailing_whitespace = true -[*.{yml,yaml,json}] +[*.{yml,yaml,js,json}] indent_size = 2 [*.md] diff --git a/hypha/addressfield/static/address_form.js b/hypha/addressfield/static/address_form.js index 34dd405a31..ba5bcd086d 100644 --- a/hypha/addressfield/static/address_form.js +++ b/hypha/addressfield/static/address_form.js @@ -1,91 +1,91 @@ (function ($) { - // add the require attribute to the field configs - function addRequiredToKey(fields, findKey) { - $.each(fields, (index, value) => { - var fieldName = Object.keys(value)[0]; - var data = value[fieldName]; - if (fieldName === findKey) { - data.required = true; - } else if (Array.isArray(data)) { - // Handle nested fields - addRequiredToKey(data, findKey); - } - }); - } + // add the require attribute to the field configs + function addRequiredToKey(fields, findKey) { + $.each(fields, (index, value) => { + var fieldName = Object.keys(value)[0]; + var data = value[fieldName]; + if (fieldName === findKey) { + data.required = true; + } else if (Array.isArray(data)) { + // Handle nested fields + addRequiredToKey(data, findKey); + } + }); + } - // hook into the transform to update with the required attribute - var oldTransform = $.fn.addressfield.transform; - $.fn.addressfield.transform = function (data) { - var mappedData = oldTransform.call(this, data); - $.each(mappedData, (key, value) => { - $.each(value.required, (index, field) => { - addRequiredToKey(mappedData[key].fields, field); - }); - }); - return mappedData; - }; + // hook into the transform to update with the required attribute + var oldTransform = $.fn.addressfield.transform; + $.fn.addressfield.transform = function (data) { + var mappedData = oldTransform.call(this, data); + $.each(mappedData, (key, value) => { + $.each(value.required, (index, field) => { + addRequiredToKey(mappedData[key].fields, field); + }); + }); + return mappedData; + }; - function labelFor(field) { - return $('label[for="' + $(field).attr("id") + '"]'); - } + function labelFor(field) { + return $('label[for="' + $(field).attr("id") + '"]'); + } - function makeFieldNotRequired(field) { - var $field = $(field); - $field.removeAttr("required"); - var $label = labelFor($field); - $label.children("span").remove(); - } + function makeFieldNotRequired(field) { + var $field = $(field); + $field.removeAttr("required"); + var $label = labelFor($field); + $label.children("span").remove(); + } - function makeFieldRequired(field) { - var $field = $(field); - $field.prop("required", true); - var $label = labelFor($field); - $label.append('*'); - } + function makeFieldRequired(field) { + var $field = $(field); + $field.prop("required", true); + var $label = labelFor($field); + $label.append('*'); + } - // Hook into the validate process to update the required display - var oldValidate = $.fn.addressfield.validate; - $.fn.addressfield.validate = function (field, config) { - if (config.required) { - makeFieldRequired(this); - } else { - makeFieldNotRequired(this); - } - oldValidate.call(this, field, config); - }; + // Hook into the validate process to update the required display + var oldValidate = $.fn.addressfield.validate; + $.fn.addressfield.validate = function (field, config) { + if (config.required) { + makeFieldRequired(this); + } else { + makeFieldNotRequired(this); + } + oldValidate.call(this, field, config); + }; - var selectWrap = '
'; + var selectWrap = ''; - // Hook into the select builder to update the display - var oldConvertToSelect = $.fn.addressfield.convertToSelect; - $.fn.addressfield.convertToSelect = function () { - var $select = oldConvertToSelect.call(this); - $select.wrap(selectWrap); - return $select; - }; + // Hook into the select builder to update the display + var oldConvertToSelect = $.fn.addressfield.convertToSelect; + $.fn.addressfield.convertToSelect = function () { + var $select = oldConvertToSelect.call(this); + $select.wrap(selectWrap); + return $select; + }; - // Hook into the text builder to update the display - var oldConvertToText = $.fn.addressfield.convertToText; - $.fn.addressfield.convertToText = function () { - var $text = oldConvertToText.call(this); - $text.unwrap(); - return $text; - }; + // Hook into the text builder to update the display + var oldConvertToText = $.fn.addressfield.convertToText; + $.fn.addressfield.convertToText = function () { + var $text = oldConvertToText.call(this); + $text.unwrap(); + return $text; + }; - $(document).ready(function formReady() { - $(".form div.address").each(function () { - $(".form div#" + this.id).addressfield({ - json: "/static/addressfield.min.json", - fields: { - country: ".country", - thoroughfare: ".thoroughfare", - premise: ".premise", - locality: ".locality", - localityname: ".localityname", - administrativearea: ".administrativearea", - postalcode: ".postalcode", - }, - }); - }); + $(document).ready(function formReady() { + $(".form div.address").each(function () { + $(".form div#" + this.id).addressfield({ + json: "/static/addressfield.min.json", + fields: { + country: ".country", + thoroughfare: ".thoroughfare", + premise: ".premise", + locality: ".locality", + localityname: ".localityname", + administrativearea: ".administrativearea", + postalcode: ".postalcode", + }, + }); }); + }); })(jQuery); diff --git a/hypha/apply/dashboard/static/js/django_select2-checkboxes.js b/hypha/apply/dashboard/static/js/django_select2-checkboxes.js index 40abe6a090..376d189207 100644 --- a/hypha/apply/dashboard/static/js/django_select2-checkboxes.js +++ b/hypha/apply/dashboard/static/js/django_select2-checkboxes.js @@ -1,39 +1,34 @@ (function ($) { - $.fn.select2.amd.require( - [ - "select2/multi-checkboxes/selection", - "select2/multi-checkboxes/results", - ], - function (SelectionAdapter, ResultsAdapter) { - $(function () { - $(".django-select2-checkboxes").each(function (i, element) { - var $element = $(element); - $element.select2({ - placeholder: $element.data("placeholder"), - closeOnSelect: false, - templateSelection: function (data) { - let filterType = $element.data("placeholder"); + $.fn.select2.amd.require( + ["select2/multi-checkboxes/selection", "select2/multi-checkboxes/results"], + function (SelectionAdapter, ResultsAdapter) { + $(function () { + $(".django-select2-checkboxes").each(function (i, element) { + var $element = $(element); + $element.select2({ + placeholder: $element.data("placeholder"), + closeOnSelect: false, + templateSelection: function (data) { + let filterType = $element.data("placeholder"); - if (!data.selected.length) { - return filterType; - } else if ( - data.selected.length == data.all.length - ) { - return "All " + filterType + " selected"; - } - return ( - data.selected.length + - " of " + - data.all.length + - " " + - filterType - ); - }, - selectionAdapter: SelectionAdapter, - returnesultsAdapter: ResultsAdapter, - }); - }); - }); - } - ); + if (!data.selected.length) { + return filterType; + } else if (data.selected.length == data.all.length) { + return "All " + filterType + " selected"; + } + return ( + data.selected.length + + " of " + + data.all.length + + " " + + filterType + ); + }, + selectionAdapter: SelectionAdapter, + returnesultsAdapter: ResultsAdapter, + }); + }); + }); + } + ); })(this.jQuery); diff --git a/hypha/apply/dashboard/static/js/select2.multi-checkboxes.js b/hypha/apply/dashboard/static/js/select2.multi-checkboxes.js index 9faf906943..6821ab8b30 100644 --- a/hypha/apply/dashboard/static/js/select2.multi-checkboxes.js +++ b/hypha/apply/dashboard/static/js/select2.multi-checkboxes.js @@ -10,120 +10,115 @@ /* global define jQuery */ (function (factory) { - if (typeof define === "function" && define.amd) { - define(["jquery"], factory); - } else { - // Browser globals - factory(jQuery); - } + if (typeof define === "function" && define.amd) { + define(["jquery"], factory); + } else { + // Browser globals + factory(jQuery); + } })(function (jQuery) { - if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) { - define = jQuery.fn.select2.amd.define; - } - var define; + if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) { + define = jQuery.fn.select2.amd.define; + } + var define; - /* global define */ - define("select2/multi-checkboxes/dropdown", [ - "select2/utils", - "select2/dropdown", - "select2/dropdown/search", - "select2/dropdown/attachBody", - ], function (Utils, Dropdown, DropdownSearch, AttachBody) { - return Utils.Decorate( - Utils.Decorate(Dropdown, DropdownSearch), - AttachBody - ); - }); + /* global define */ + define("select2/multi-checkboxes/dropdown", [ + "select2/utils", + "select2/dropdown", + "select2/dropdown/search", + "select2/dropdown/attachBody", + ], function (Utils, Dropdown, DropdownSearch, AttachBody) { + return Utils.Decorate(Utils.Decorate(Dropdown, DropdownSearch), AttachBody); + }); - /* global define */ - define("select2/multi-checkboxes/results", [ - "jquery", - "select2/utils", - "select2/results", - ], function ($, Utils, _Results) { - function Results() { - Results.__super__.constructor.apply(this, arguments); - } - Utils.Extend(Results, _Results); + /* global define */ + define("select2/multi-checkboxes/results", [ + "jquery", + "select2/utils", + "select2/results", + ], function ($, Utils, _Results) { + function Results() { + Results.__super__.constructor.apply(this, arguments); + } + Utils.Extend(Results, _Results); - Results.prototype.highlightFirstItem = function () { - this.ensureHighlightVisible(); - }; + Results.prototype.highlightFirstItem = function () { + this.ensureHighlightVisible(); + }; - Results.prototype.bind = function (container) { - container.on("open", function () { - var $options = this.$results.find( - ".select2-results__option[aria-selected]" - ); - var $selected = $options.filter("[aria-selected=true]"); - var $optionToScrollTo = ( - $selected.length > 0 ? $selected : $selected - ).first(); - $optionToScrollTo.trigger("mouseenter"); - }); - Results.__super__.bind.apply(this, arguments); - }; + Results.prototype.bind = function (container) { + container.on("open", function () { + var $options = this.$results.find( + ".select2-results__option[aria-selected]" + ); + var $selected = $options.filter("[aria-selected=true]"); + var $optionToScrollTo = ( + $selected.length > 0 ? $selected : $selected + ).first(); + $optionToScrollTo.trigger("mouseenter"); + }); + Results.__super__.bind.apply(this, arguments); + }; - Results.prototype.template = function (result, container) { - var template = this.options.get("templateResult"); - var escapeMarkup = this.options.get("escapeMarkup"); + Results.prototype.template = function (result, container) { + var template = this.options.get("templateResult"); + var escapeMarkup = this.options.get("escapeMarkup"); - var content = template(result, container); - $(container).addClass("multi-checkboxes_wrap"); + var content = template(result, container); + $(container).addClass("multi-checkboxes_wrap"); - if (content == null) { - container.style.display = "none"; - } else if (typeof content === "string") { - container.innerHTML = escapeMarkup(content); - } else { - $(container).append(content); - } - }; + if (content == null) { + container.style.display = "none"; + } else if (typeof content === "string") { + container.innerHTML = escapeMarkup(content); + } else { + $(container).append(content); + } + }; - return Results; - }); + return Results; + }); - /* global define */ - define("select2/multi-checkboxes/selection", [ - "select2/utils", - "select2/selection/multiple", - "select2/selection/placeholder", - "select2/selection/single", - "select2/selection/eventRelay", - ], function ( - Utils, - MultipleSelection, - Placeholder, - SingleSelection, - EventRelay - ) { - var adapter = Utils.Decorate(MultipleSelection, Placeholder); - adapter = Utils.Decorate(adapter, EventRelay); + /* global define */ + define("select2/multi-checkboxes/selection", [ + "select2/utils", + "select2/selection/multiple", + "select2/selection/placeholder", + "select2/selection/single", + "select2/selection/eventRelay", + ], function ( + Utils, + MultipleSelection, + Placeholder, + SingleSelection, + EventRelay + ) { + var adapter = Utils.Decorate(MultipleSelection, Placeholder); + adapter = Utils.Decorate(adapter, EventRelay); - adapter.prototype.render = function () { - return SingleSelection.prototype.render.call(this); - }; + adapter.prototype.render = function () { + return SingleSelection.prototype.render.call(this); + }; - adapter.prototype.update = function (data) { - var $rendered = this.$selection.find( - ".select2-selection__rendered" - ); - var formatted = ""; + adapter.prototype.update = function (data) { + var $rendered = this.$selection.find(".select2-selection__rendered"); + var formatted = ""; - if (data.length === 0) { - formatted = this.options.get("placeholder") || ""; - } else { - var itemsData = { - selected: data || [], - all: this.$element.find("option") || [], - }; - formatted = this.display(itemsData, $rendered); - } - - $rendered.empty().append(formatted); - $rendered.prop("title", formatted); + if (data.length === 0) { + formatted = this.options.get("placeholder") || ""; + } else { + var itemsData = { + selected: data || [], + all: this.$element.find("option") || [], }; + formatted = this.display(itemsData, $rendered); + } + + $rendered.empty().append(formatted); + $rendered.prop("title", formatted); + }; - return adapter; - }); + return adapter; + }); }); diff --git a/hypha/cookieconsent/static/js/cookieconsent.js b/hypha/cookieconsent/static/js/cookieconsent.js index 3a33c43b68..a9306f9d81 100644 --- a/hypha/cookieconsent/static/js/cookieconsent.js +++ b/hypha/cookieconsent/static/js/cookieconsent.js @@ -1,124 +1,122 @@ (function () { - // Used when an analytics cookie notice is enabled - const ACCEPT = "accept"; - const DECLINE = "decline"; - const ACK = "ack"; // Only for essential cookies + // Used when an analytics cookie notice is enabled + const ACCEPT = "accept"; + const DECLINE = "decline"; + const ACK = "ack"; // Only for essential cookies - // Constant key used for localstorage - const COOKIECONSENT_KEY = "cookieconsent"; + // Constant key used for localstorage + const COOKIECONSENT_KEY = "cookieconsent"; - // Class constants - const CLASS_COOKIECONSENT = "cookieconsent"; - const CLASS_LEARNMORE = "cookieconsent__learnmore"; - const CLASS_COOKIEBRIEF = "cookieconsent__brief"; - const CLASS_COOKIECONTENT = "cookieconsent__content"; - const CLASS_JS_CONSENT_OPEN = "js-cookieconsent-open"; - const CLASS_JS_LEARNMORE = "js-cookieconsent-show-learnmore"; - const CLASS_JS_LEARNMORE_EXPAND = `${CLASS_JS_LEARNMORE}-expand`; + // Class constants + const CLASS_COOKIECONSENT = "cookieconsent"; + const CLASS_LEARNMORE = "cookieconsent__learnmore"; + const CLASS_COOKIEBRIEF = "cookieconsent__brief"; + const CLASS_COOKIECONTENT = "cookieconsent__content"; + const CLASS_JS_CONSENT_OPEN = "js-cookieconsent-open"; + const CLASS_JS_LEARNMORE = "js-cookieconsent-show-learnmore"; + const CLASS_JS_LEARNMORE_EXPAND = `${CLASS_JS_LEARNMORE}-expand`; - const cookieconsent = document.querySelector(`.${CLASS_COOKIECONSENT}`); - if (!cookieconsent) { - return; - } + const cookieconsent = document.querySelector(`.${CLASS_COOKIECONSENT}`); + if (!cookieconsent) { + return; + } - const cookieButtons = cookieconsent.querySelectorAll( - "button[data-consent]" - ); - const learnMoreToggles = cookieconsent.querySelectorAll( - ".button--learn-more" - ); + const cookieButtons = cookieconsent.querySelectorAll("button[data-consent]"); + const learnMoreToggles = cookieconsent.querySelectorAll( + ".button--learn-more" + ); - /** - * Pull the cookie consent value from localStorage - * - * @returns {(string|null)} A string if consent value exists, null if not - */ - function getConsentValue() { - return localStorage.getItem(COOKIECONSENT_KEY); - } + /** + * Pull the cookie consent value from localStorage + * + * @returns {(string|null)} A string if consent value exists, null if not + */ + function getConsentValue() { + return localStorage.getItem(COOKIECONSENT_KEY); + } - /** - * Set the cookie consent value in localStorage - * - * @param {("accept"|"decline"|"ack")} value - consent value to set - */ - function setConsentValue(value) { - if ([ACCEPT, DECLINE, ACK].includes(value)) { - localStorage.setItem(COOKIECONSENT_KEY, value); - } else { - // If for whatever reason the value is not in the predefined values, assume decline - localStorage.setItem(COOKIECONSENT_KEY, DECLINE); - } + /** + * Set the cookie consent value in localStorage + * + * @param {("accept"|"decline"|"ack")} value - consent value to set + */ + function setConsentValue(value) { + if ([ACCEPT, DECLINE, ACK].includes(value)) { + localStorage.setItem(COOKIECONSENT_KEY, value); + } else { + // If for whatever reason the value is not in the predefined values, assume decline + localStorage.setItem(COOKIECONSENT_KEY, DECLINE); } + } - /** - * Trigger the cookie consent prompt to open - */ - function openConsentPrompt() { - cookieconsent.classList.add(CLASS_JS_CONSENT_OPEN); - } + /** + * Trigger the cookie consent prompt to open + */ + function openConsentPrompt() { + cookieconsent.classList.add(CLASS_JS_CONSENT_OPEN); + } - /** - * Trigger cookie consent prompt to close - */ - function closeConsentPrompt() { - cookieconsent.classList.remove(CLASS_JS_CONSENT_OPEN); - } + /** + * Trigger cookie consent prompt to close + */ + function closeConsentPrompt() { + cookieconsent.classList.remove(CLASS_JS_CONSENT_OPEN); + } - // Expose consent prompt opening/closing globally (ie. to use in a footer) - window.openConsentPrompt = openConsentPrompt; - window.closeConsentPrompt = closeConsentPrompt; + // Expose consent prompt opening/closing globally (ie. to use in a footer) + window.openConsentPrompt = openConsentPrompt; + window.closeConsentPrompt = closeConsentPrompt; - /** - * Trigger the "Learn More" prompt on the cookie banner to open/close - * - * @param {boolean} open - true to open learn more prompt, false to close - */ - function toggleLearnMore(open) { - const content = cookieconsent.querySelector(`.${CLASS_COOKIECONTENT}`); - if (open) { - content.classList.add(CLASS_JS_LEARNMORE); - cookieconsent.classList.add(CLASS_JS_LEARNMORE_EXPAND); - } else { - content.classList.remove(CLASS_JS_LEARNMORE); - cookieconsent.classList.remove(CLASS_JS_LEARNMORE_EXPAND); - } - setInputTabIndex(`.${CLASS_LEARNMORE}`, open ? 0 : -1); - setInputTabIndex(`.${CLASS_COOKIEBRIEF}`, open ? -1 : 0); + /** + * Trigger the "Learn More" prompt on the cookie banner to open/close + * + * @param {boolean} open - true to open learn more prompt, false to close + */ + function toggleLearnMore(open) { + const content = cookieconsent.querySelector(`.${CLASS_COOKIECONTENT}`); + if (open) { + content.classList.add(CLASS_JS_LEARNMORE); + cookieconsent.classList.add(CLASS_JS_LEARNMORE_EXPAND); + } else { + content.classList.remove(CLASS_JS_LEARNMORE); + cookieconsent.classList.remove(CLASS_JS_LEARNMORE_EXPAND); } + setInputTabIndex(`.${CLASS_LEARNMORE}`, open ? 0 : -1); + setInputTabIndex(`.${CLASS_COOKIEBRIEF}`, open ? -1 : 0); + } - /** - * Adds "tabability" to menu buttons/toggles - * - * @param {string} wrapperClassSelector - wrapper class to set tabability of inputs on - * @param {number} tabValue - tab index value to set on all input items in the wrapper class - */ - function setInputTabIndex(wrapperClassSelector, tabValue) { - const wrapper = cookieconsent.querySelector(wrapperClassSelector); - const tabables = wrapper.querySelectorAll("button, input"); - tabables.forEach((element) => (element.tabIndex = tabValue)); - } + /** + * Adds "tabability" to menu buttons/toggles + * + * @param {string} wrapperClassSelector - wrapper class to set tabability of inputs on + * @param {number} tabValue - tab index value to set on all input items in the wrapper class + */ + function setInputTabIndex(wrapperClassSelector, tabValue) { + const wrapper = cookieconsent.querySelector(wrapperClassSelector); + const tabables = wrapper.querySelectorAll("button, input"); + tabables.forEach((element) => (element.tabIndex = tabValue)); + } - // Open the prompt if consent value is undefined OR if analytics has been added since the user ack'd essential cookies - if ( - getConsentValue() == null || - (getConsentValue() === ACK && cookieButtons.length > 2) - ) { - openConsentPrompt(); - } + // Open the prompt if consent value is undefined OR if analytics has been added since the user ack'd essential cookies + if ( + getConsentValue() == null || + (getConsentValue() === ACK && cookieButtons.length > 2) + ) { + openConsentPrompt(); + } - cookieButtons.forEach(function (button) { - button.addEventListener("click", function () { - const buttonValue = button.getAttribute("data-consent"); - setConsentValue(buttonValue); - closeConsentPrompt(); - }); + cookieButtons.forEach(function (button) { + button.addEventListener("click", function () { + const buttonValue = button.getAttribute("data-consent"); + setConsentValue(buttonValue); + closeConsentPrompt(); }); + }); - learnMoreToggles.forEach(function (button) { - button.addEventListener("click", function () { - const buttonValue = button.getAttribute("show-learn-more"); - toggleLearnMore(buttonValue === "true"); - }); + learnMoreToggles.forEach(function (button) { + button.addEventListener("click", function () { + const buttonValue = button.getAttribute("show-learn-more"); + toggleLearnMore(buttonValue === "true"); }); + }); })(); diff --git a/hypha/static_src/javascript/all-submissions-table.js b/hypha/static_src/javascript/all-submissions-table.js index 412498d39f..d97550d9fe 100644 --- a/hypha/static_src/javascript/all-submissions-table.js +++ b/hypha/static_src/javascript/all-submissions-table.js @@ -1,30 +1,30 @@ (function () { - let submission_arrow = document.createElement("span"); - submission_arrow.classList.add("arrow"); + let submission_arrow = document.createElement("span"); + submission_arrow.classList.add("arrow"); - let submission_toggle = document.createElement("button"); - submission_toggle.classList.add( - "all-submissions-table__toggle", - "js-toggle-submission" - ); - submission_toggle.setAttribute("title", "Show submission details"); - submission_toggle.appendChild(submission_arrow); + let submission_toggle = document.createElement("button"); + submission_toggle.classList.add( + "all-submissions-table__toggle", + "js-toggle-submission" + ); + submission_toggle.setAttribute("title", "Show submission details"); + submission_toggle.appendChild(submission_arrow); - // Add the toggle arrow before the submission titles. - const submission_titles = document.querySelectorAll( - ".all-submissions-table__parent > td.title" - ); - submission_titles.forEach(function (title) { - title.prepend(submission_toggle.cloneNode(true)); - }); + // Add the toggle arrow before the submission titles. + const submission_titles = document.querySelectorAll( + ".all-submissions-table__parent > td.title" + ); + submission_titles.forEach(function (title) { + title.prepend(submission_toggle.cloneNode(true)); + }); - // Show/hide the submission child rows. - const children = document.querySelectorAll(".js-toggle-submission"); - children.forEach(function (child) { - child.addEventListener("click", (e) => { - e.target - .closest(".all-submissions-table__parent") - .classList.toggle("is-expanded"); - }); + // Show/hide the submission child rows. + const children = document.querySelectorAll(".js-toggle-submission"); + children.forEach(function (child) { + child.addEventListener("click", (e) => { + e.target + .closest(".all-submissions-table__parent") + .classList.toggle("is-expanded"); }); + }); })(); diff --git a/hypha/static_src/javascript/application-form-links-new-window.js b/hypha/static_src/javascript/application-form-links-new-window.js index b6ef3ce5d9..9bfb21fa9b 100644 --- a/hypha/static_src/javascript/application-form-links-new-window.js +++ b/hypha/static_src/javascript/application-form-links-new-window.js @@ -1,8 +1,8 @@ (function () { - // Make links on application forms open in a new window/tab. - const links = document.querySelectorAll(".application-form a"); - links.forEach(function (link) { - link.setAttribute("target", "_blank"); - link.setAttribute("rel", "noopener noreferrer"); - }); + // Make links on application forms open in a new window/tab. + const links = document.querySelectorAll(".application-form a"); + links.forEach(function (link) { + link.setAttribute("target", "_blank"); + link.setAttribute("rel", "noopener noreferrer"); + }); })(); diff --git a/hypha/static_src/javascript/application-form.js b/hypha/static_src/javascript/application-form.js index 096fb7f8ad..c0d71a45af 100644 --- a/hypha/static_src/javascript/application-form.js +++ b/hypha/static_src/javascript/application-form.js @@ -1,69 +1,69 @@ (function () { - const form = document.querySelector(".application-form"); - const button = form.querySelector("[type=submit]"); - const required = form.querySelectorAll("input[required]"); - const groups = form.querySelectorAll(".form__group"); - const errors = form.querySelectorAll(".form__error"); + const form = document.querySelector(".application-form"); + const button = form.querySelector("[type=submit]"); + const required = form.querySelectorAll("input[required]"); + const groups = form.querySelectorAll(".form__group"); + const errors = form.querySelectorAll(".form__error"); - // Set aria-required attribute true for required fields. - required.forEach(function (field) { - field.setAttribute("aria-required", true); - }); - - // Add label_id as aria-describedby to help text. - groups.forEach(function (group) { - const label = group.querySelector("label"); - if (label) { - const label_id = label.getAttribute("for"); - if (group.querySelector(".form__help")) { - group - .querySelector(".form__help") - .setAttribute("aria-describedby", label_id); - } - } - }); + // Set aria-required attribute true for required fields. + required.forEach(function (field) { + field.setAttribute("aria-required", true); + }); - if (errors.length) { - // Set focus to the first error field. - const first_error = errors[0].querySelector("input"); - if (first_error) { - first_error.focus(); - } + // Add label_id as aria-describedby to help text. + groups.forEach(function (group) { + const label = group.querySelector("label"); + if (label) { + const label_id = label.getAttribute("for"); + if (group.querySelector(".form__help")) { + group + .querySelector(".form__help") + .setAttribute("aria-describedby", label_id); + } + } + }); - // Set aria-invalid for field with errors. - errors.forEach(function (error) { - const input = error.querySelector("input, textarea"); - if (input) { - input.setAttribute("aria-invalid", true); - } - }); + if (errors.length) { + // Set focus to the first error field. + const first_error = errors[0].querySelector("input"); + if (first_error) { + first_error.focus(); } - // Remove the "no javascript" messages - document.querySelector(".message-no-js").remove(); + // Set aria-invalid for field with errors. + errors.forEach(function (error) { + const input = error.querySelector("input, textarea"); + if (input) { + input.setAttribute("aria-invalid", true); + } + }); + } - const unlockApplicationForm = function () { - form.setAttribute("action", ""); - button.removeAttribute("disabled"); - }; + // Remove the "no javascript" messages + document.querySelector(".message-no-js").remove(); - // Unlock form on - // 1. mouse move - // 2. touch move - // 3. tab or enter key pressed - document.body.addEventListener("mousemove", unlockApplicationForm, { - once: true, - }); - document.body.addEventListener("touchmove", unlockApplicationForm, { - once: true, - }); - document.body.addEventListener( - "keydown", - function (e) { - if (e.key === "Tab" || e.key === "Enter") { - unlockApplicationForm(); - } - }, - { once: true } - ); + const unlockApplicationForm = function () { + form.setAttribute("action", ""); + button.removeAttribute("disabled"); + }; + + // Unlock form on + // 1. mouse move + // 2. touch move + // 3. tab or enter key pressed + document.body.addEventListener("mousemove", unlockApplicationForm, { + once: true, + }); + document.body.addEventListener("touchmove", unlockApplicationForm, { + once: true, + }); + document.body.addEventListener( + "keydown", + function (e) { + if (e.key === "Tab" || e.key === "Enter") { + unlockApplicationForm(); + } + }, + { once: true } + ); })(); diff --git a/hypha/static_src/javascript/batch-actions.js b/hypha/static_src/javascript/batch-actions.js index 38877cdc63..d887ce2207 100644 --- a/hypha/static_src/javascript/batch-actions.js +++ b/hypha/static_src/javascript/batch-actions.js @@ -1,172 +1,170 @@ /* eslint-disable max-nested-callbacks */ (function ($) { - const $body = $("body"); - const $checkbox = $(".js-batch-select"); - const $allCheckboxInput = $(".js-batch-select-all"); - const $batchButtons = $(".js-batch-button"); - const $batchInvoiceProgress = $(".js-batch-invoice-progress"); - const $batchTitlesList = $(".js-batch-titles"); - const $batchTitleCount = $(".js-batch-title-count"); - const $hiddenIDlist = $(".js-submissions-id"); - const $hiddenInvoiceIDlist = $(".js-invoices-id"); - const $toggleBatchList = $(".js-toggle-batch-list"); - const activeClass = "batch-actions-enabled"; - const closedClass = "is-closed"; - - $(window).on("load", function () { - toggleBatchActions(); - updateCount(); - }); - - $allCheckboxInput.change(function () { - if ($(this).is(":checked")) { - $checkbox.each(function () { - this.checked = true; - }); - } else { - $checkbox.each(function () { - this.checked = false; - }); - } - - toggleBatchActions(); - updateCount(); - updateInvoiceProgressButton(); - }); + const $body = $("body"); + const $checkbox = $(".js-batch-select"); + const $allCheckboxInput = $(".js-batch-select-all"); + const $batchButtons = $(".js-batch-button"); + const $batchInvoiceProgress = $(".js-batch-invoice-progress"); + const $batchTitlesList = $(".js-batch-titles"); + const $batchTitleCount = $(".js-batch-title-count"); + const $hiddenIDlist = $(".js-submissions-id"); + const $hiddenInvoiceIDlist = $(".js-invoices-id"); + const $toggleBatchList = $(".js-toggle-batch-list"); + const activeClass = "batch-actions-enabled"; + const closedClass = "is-closed"; + + $(window).on("load", function () { + toggleBatchActions(); + updateCount(); + }); + + $allCheckboxInput.change(function () { + if ($(this).is(":checked")) { + $checkbox.each(function () { + this.checked = true; + }); + } else { + $checkbox.each(function () { + this.checked = false; + }); + } - $checkbox.change(function () { - // see how many checkboxes are :checked - toggleBatchActions(); + toggleBatchActions(); + updateCount(); + updateInvoiceProgressButton(); + }); - // updates selected checbox count - updateCount(); + $checkbox.change(function () { + // see how many checkboxes are :checked + toggleBatchActions(); - // reset the check all input - if (!$(this).is(":checked") && $allCheckboxInput.is(":checked")) { - resetCheckAllInput(); - } + // updates selected checbox count + updateCount(); - updateInvoiceProgressButton(); - }); + // reset the check all input + if (!$(this).is(":checked") && $allCheckboxInput.is(":checked")) { + resetCheckAllInput(); + } - // append selected project titles to batch update reviewer modal - $batchButtons.each(function () { - $(this).click(function (e) { - let selectedIDs = []; - e.preventDefault(); - selectedIDs = prepareBatchListing(); - - if (selectedIDs.length > 0) { - // Get the base URL from the href attribute - const baseUrl = $(this).attr("href"); - const url = new URL(baseUrl, window.location.origin); - selectedIDs.forEach((id) => { - url.searchParams.append("selected_ids", id); - }); - // Send the request using htmx.ajax - htmx.ajax("GET", url.toString(), { - target: "#htmx-modal", // Optional: set the target element - }); - } else { - alert("Please select at least one item."); - } + updateInvoiceProgressButton(); + }); + + // append selected project titles to batch update reviewer modal + $batchButtons.each(function () { + $(this).click(function (e) { + let selectedIDs = []; + e.preventDefault(); + selectedIDs = prepareBatchListing(); + + if (selectedIDs.length > 0) { + // Get the base URL from the href attribute + const baseUrl = $(this).attr("href"); + const url = new URL(baseUrl, window.location.origin); + selectedIDs.forEach((id) => { + url.searchParams.append("selected_ids", id); }); + // Send the request using htmx.ajax + htmx.ajax("GET", url.toString(), { + target: "#htmx-modal", // Optional: set the target element + }); + } else { + alert("Please select at least one item."); + } }); + }); - $batchInvoiceProgress.click(function () { - updateInvoiceProgressButton(); - }); - - // show/hide the list of actions - $toggleBatchList.click((e) => { - e.preventDefault(); + $batchInvoiceProgress.click(function () { + updateInvoiceProgressButton(); + }); - if ($(".js-batch-titles").hasClass(closedClass)) { - $toggleBatchList.html("Hide"); - } else { - $toggleBatchList.html("Show"); - } - - $batchTitlesList.toggleClass(closedClass); - }); + // show/hide the list of actions + $toggleBatchList.click((e) => { + e.preventDefault(); - /** - * Prepare the batch listing. - * @returns {Array} selectedIDs - */ - function prepareBatchListing() { - $batchTitlesList.html(""); - $batchTitleCount.html(""); - $batchTitlesList.addClass(closedClass); - $toggleBatchList.html("Show"); + if ($(".js-batch-titles").hasClass(closedClass)) { + $toggleBatchList.html("Hide"); + } else { + $toggleBatchList.html("Show"); + } - let selectedIDs = []; + $batchTitlesList.toggleClass(closedClass); + }); - $checkbox.filter(":checked").each(function () { - selectedIDs.push($(this).parents("tr").data("record-id")); - }); + /** + * Prepare the batch listing. + * @returns {Array} selectedIDs + */ + function prepareBatchListing() { + $batchTitlesList.html(""); + $batchTitleCount.html(""); + $batchTitlesList.addClass(closedClass); + $toggleBatchList.html("Show"); - $batchTitleCount.append(`${selectedIDs.length} submissions selected`); - $hiddenIDlist.val(selectedIDs.join(",")); - $hiddenInvoiceIDlist.val(selectedIDs.join(",")); - return selectedIDs; - } - - /** - * Update the invoice progress button. - */ - function updateInvoiceProgressButton() { - var actions; - $checkbox.filter(":checked").each(function () { - let newActions = $(this) - .parents("tr") - .find(".js-actions") - .data("actions"); - // If actions is undefined (i.e., first iteration), initialize it with newActions - if (!actions) { - actions = newActions; - } else { - // Filter actions to keep only items also present in newActions - actions = actions.filter((action) => - newActions.includes(action) - ); - } - }); + let selectedIDs = []; - if (!actions || actions.length === 0) { - $batchInvoiceProgress.attr("disabled", "disabled"); - $batchInvoiceProgress.attr( - "data-tooltip", - "Status changes can't be applied to Invoices with this combination of statuses" - ); - } else { - $batchInvoiceProgress.removeAttr("disabled"); - $batchInvoiceProgress.removeAttr("data-tooltip"); - } - } + $checkbox.filter(":checked").each(function () { + selectedIDs.push($(this).parents("tr").data("record-id")); + }); - /** - * Toggle the batch actions. - */ - function toggleBatchActions() { - if ($(".js-batch-select:checked").length) { - $body.addClass(activeClass); - } else { - $body.removeClass(activeClass); - } - } + $batchTitleCount.append(`${selectedIDs.length} submissions selected`); + $hiddenIDlist.val(selectedIDs.join(",")); + $hiddenInvoiceIDlist.val(selectedIDs.join(",")); + return selectedIDs; + } + + /** + * Update the invoice progress button. + */ + function updateInvoiceProgressButton() { + var actions; + $checkbox.filter(":checked").each(function () { + let newActions = $(this) + .parents("tr") + .find(".js-actions") + .data("actions"); + // If actions is undefined (i.e., first iteration), initialize it with newActions + if (!actions) { + actions = newActions; + } else { + // Filter actions to keep only items also present in newActions + actions = actions.filter((action) => newActions.includes(action)); + } + }); - /** - * Update the count of selected checkboxes. - */ - function updateCount() { - $(".js-total-actions").html($(".js-batch-select:checked").length); + if (!actions || actions.length === 0) { + $batchInvoiceProgress.attr("disabled", "disabled"); + $batchInvoiceProgress.attr( + "data-tooltip", + "Status changes can't be applied to Invoices with this combination of statuses" + ); + } else { + $batchInvoiceProgress.removeAttr("disabled"); + $batchInvoiceProgress.removeAttr("data-tooltip"); } - - /** - * Reset the check all input. - */ - function resetCheckAllInput() { - $allCheckboxInput.prop("checked", false); + } + + /** + * Toggle the batch actions. + */ + function toggleBatchActions() { + if ($(".js-batch-select:checked").length) { + $body.addClass(activeClass); + } else { + $body.removeClass(activeClass); } + } + + /** + * Update the count of selected checkboxes. + */ + function updateCount() { + $(".js-total-actions").html($(".js-batch-select:checked").length); + } + + /** + * Reset the check all input. + */ + function resetCheckAllInput() { + $allCheckboxInput.prop("checked", false); + } })(jQuery); diff --git a/hypha/static_src/javascript/behaviours/collapse.js b/hypha/static_src/javascript/behaviours/collapse.js index e6dc404c92..07085555a1 100644 --- a/hypha/static_src/javascript/behaviours/collapse.js +++ b/hypha/static_src/javascript/behaviours/collapse.js @@ -8,47 +8,47 @@ * */ (function () { - document.addEventListener("DOMContentLoaded", function () { - // Select the element with the data-js-collapse attribute - const el = document.querySelector("[data-js-collapse]"); - if (!el) { - return; - } + document.addEventListener("DOMContentLoaded", function () { + // Select the element with the data-js-collapse attribute + const el = document.querySelector("[data-js-collapse]"); + if (!el) { + return; + } - // Get the current full height of the content - const content_height = el.getBoundingClientRect().height; - // Read the max height from the data-js-collapse attribute - // If the attribute is not set, use the default value - const content_max_height = - parseInt(el.getAttribute("data-js-collapse-height")) || 320; + // Get the current full height of the content + const content_height = el.getBoundingClientRect().height; + // Read the max height from the data-js-collapse attribute + // If the attribute is not set, use the default value + const content_max_height = + parseInt(el.getAttribute("data-js-collapse-height")) || 320; - // If the content height is less than or equal to the max height, do nothing - if (content_height <= content_max_height) { - return; - } + // If the content height is less than or equal to the max height, do nothing + if (content_height <= content_max_height) { + return; + } - // Create a "Show" button - const btn_show = document.createElement("button"); - btn_show.classList.add("button", "button--primary", "button--narrow"); - btn_show.textContent = "Show"; + // Create a "Show" button + const btn_show = document.createElement("button"); + btn_show.classList.add("button", "button--primary", "button--narrow"); + btn_show.textContent = "Show"; - // Create a wrapper for the button with gradient background - const btn_wrapper = document.createElement("div"); - btn_wrapper.classList.add( - ..."w-full absolute bottom-0 left-0 text-center pt-8 pb-4 bg-gradient-to-t from-white".split( - " " - ) - ); - btn_wrapper.appendChild(btn_show); + // Create a wrapper for the button with gradient background + const btn_wrapper = document.createElement("div"); + btn_wrapper.classList.add( + ..."w-full absolute bottom-0 left-0 text-center pt-8 pb-4 bg-gradient-to-t from-white".split( + " " + ) + ); + btn_wrapper.appendChild(btn_show); - el.append(btn_wrapper); - el.classList.add("relative", "overflow-hidden"); - el.style.maxHeight = `${content_max_height}px`; + el.append(btn_wrapper); + el.classList.add("relative", "overflow-hidden"); + el.style.maxHeight = `${content_max_height}px`; - // Add click event listener to show full content - btn_show.addEventListener("click", function () { - el.style.maxHeight = "none"; - btn_wrapper.remove(); - }); + // Add click event listener to show full content + btn_show.addEventListener("click", function () { + el.style.maxHeight = "none"; + btn_wrapper.remove(); }); + }); })(); diff --git a/hypha/static_src/javascript/behaviours/review-score.js b/hypha/static_src/javascript/behaviours/review-score.js index 7629a30042..1ee6a6d100 100644 --- a/hypha/static_src/javascript/behaviours/review-score.js +++ b/hypha/static_src/javascript/behaviours/review-score.js @@ -3,50 +3,43 @@ * @returns {object} The review score component object. */ document.addEventListener("alpine:init", () => { - Alpine.data("reviewScore", () => { - return { - /** @type {number} The calculated review score. */ - totalScore: 0, + Alpine.data("reviewScore", () => { + return { + /** @type {number} The calculated review score. */ + totalScore: 0, - /** - * Initializes the component. - * Sets up event listeners for score calculation if applicable. - */ - init() { - this.selectors = - this.$el.querySelectorAll("[data-score-field]"); - if (this.showScore) { - this.calculateScore(); - this.selectors.forEach((selector) => { - selector.addEventListener( - "change", - this.calculateScore.bind(this) - ); - }); - } - }, + /** + * Initializes the component. + * Sets up event listeners for score calculation if applicable. + */ + init() { + this.selectors = this.$el.querySelectorAll("[data-score-field]"); + if (this.showScore) { + this.calculateScore(); + this.selectors.forEach((selector) => { + selector.addEventListener("change", this.calculateScore.bind(this)); + }); + } + }, - /** - * Calculates the total score based on valid selector values. - */ - calculateScore() { - const validValues = [...this.selectors] - .map((selector) => parseInt(selector.value)) - .filter((value) => !isNaN(value) && value !== 99); + /** + * Calculates the total score based on valid selector values. + */ + calculateScore() { + const validValues = [...this.selectors] + .map((selector) => parseInt(selector.value)) + .filter((value) => !isNaN(value) && value !== 99); - this.totalScore = validValues.reduce( - (sum, value) => sum + value, - 0 - ); - }, + this.totalScore = validValues.reduce((sum, value) => sum + value, 0); + }, - /** - * Determines if the score should be shown. - * @returns {boolean} True if there are selectors, false otherwise. - */ - get showScore() { - return this.selectors.length > 0; - }, - }; - }); + /** + * Determines if the score should be shown. + * @returns {boolean} True if there are selectors, false otherwise. + */ + get showScore() { + return this.selectors.length > 0; + }, + }; + }); }); diff --git a/hypha/static_src/javascript/deliverables.js b/hypha/static_src/javascript/deliverables.js index a42506ee84..5979130de0 100644 --- a/hypha/static_src/javascript/deliverables.js +++ b/hypha/static_src/javascript/deliverables.js @@ -1,135 +1,135 @@ (function ($) { - $("#deliverables").on("change", function (e) { - e.preventDefault(); - var $selected = $(this).find("option:selected"); - $(".available-to-invoice").find(".availablequantity").remove(); - var availabletoinvoice = $selected.data("availabletoinvoice"); - if (availabletoinvoice) { - $(".available-to-invoice").append( - '' + availabletoinvoice + "" - ); - } - }); + $("#deliverables").on("change", function (e) { + e.preventDefault(); + var $selected = $(this).find("option:selected"); + $(".available-to-invoice").find(".availablequantity").remove(); + var availabletoinvoice = $selected.data("availabletoinvoice"); + if (availabletoinvoice) { + $(".available-to-invoice").append( + '' + availabletoinvoice + "" + ); + } + }); - $("#add-deliverables").on("submit", function (event) { - event.preventDefault(); + $("#add-deliverables").on("submit", function (event) { + event.preventDefault(); - var $form = $(this); - var projectid = $form.data("projectid"); - var invoiceid = $form.data("invoiceid"); - var deliverableid = $("#deliverables").val(); - var quantity = $form.find('input[name="quantity"]').val(); - if (!quantity) { - quantity = 1; - } - $.ajax({ - url: - "/api/v1/projects/" + - projectid + - "/invoices/" + - invoiceid + - "/deliverables/", - type: "POST", - data: { id: deliverableid, quantity: quantity }, - success: function (json) { - $("#add-deliverables").find(".error").remove(); - $("#list-deliverables").find(".deliverables").remove(); - $("#list-deliverables").find(".total").remove(); - var deliverables = $(''); - var deliverable_items = json.deliverables; - $.each(deliverable_items, function (i) { - var url = - "/api/v1/projects/" + - deliverable_items[i]["project_id"] + - "/invoices/" + - deliverable_items[i]["invoice_id"] + - "/deliverables/"; - var deliverable = $( - "" + - deliverable_items[i]["deliverable"]["name"] + - " (" + - deliverable_items[i]["quantity"] + - " $" + - deliverable_items[i]["deliverable"]["unit_price"] + - ') Remove' + - json.responseJSON.detail + - "
" - ); - $("#add-deliverables").append(errorText); - }, + var $form = $(this); + var projectid = $form.data("projectid"); + var invoiceid = $form.data("invoiceid"); + var deliverableid = $("#deliverables").val(); + var quantity = $form.find('input[name="quantity"]').val(); + if (!quantity) { + quantity = 1; + } + $.ajax({ + url: + "/api/v1/projects/" + + projectid + + "/invoices/" + + invoiceid + + "/deliverables/", + type: "POST", + data: { id: deliverableid, quantity: quantity }, + success: function (json) { + $("#add-deliverables").find(".error").remove(); + $("#list-deliverables").find(".deliverables").remove(); + $("#list-deliverables").find(".total").remove(); + var deliverables = $(''); + var deliverable_items = json.deliverables; + $.each(deliverable_items, function (i) { + var url = + "/api/v1/projects/" + + deliverable_items[i]["project_id"] + + "/invoices/" + + deliverable_items[i]["invoice_id"] + + "/deliverables/"; + var deliverable = $( + "" + + deliverable_items[i]["deliverable"]["name"] + + " (" + + deliverable_items[i]["quantity"] + + " $" + + deliverable_items[i]["deliverable"]["unit_price"] + + ') Remove' + + json.responseJSON.detail + + "
" + ); + $("#add-deliverables").append(errorText); + }, }); - $("#list-deliverables").on("click", "a", function (event) { - event.preventDefault(); - $.ajax({ - url: $(this).attr("href"), - type: "DELETE", - success: function (json) { - $("#add-deliverables").find(".error").remove(); - $("#list-deliverables").find(".deliverables").remove(); - $("#list-deliverables").find(".total").remove(); - var deliverables = $(''); - var deliverable_items = json.deliverables; - $.each(deliverable_items, function (i) { - var url = - "/api/v1/projects/" + - deliverable_items[i]["project_id"] + - "/invoices/" + - deliverable_items[i]["invoice_id"] + - "/deliverables/"; - var deliverable = $( - "" + - deliverable_items[i]["deliverable"]["name"] + - " (" + - deliverable_items[i]["quantity"] + - " $" + - deliverable_items[i]["deliverable"]["unit_price"] + - ') Remove' + - json.responseJSON.detail + - "
" - ); - $("#add-deliverables").append(errorText); - }, + }); + $("#list-deliverables").on("click", "a", function (event) { + event.preventDefault(); + $.ajax({ + url: $(this).attr("href"), + type: "DELETE", + success: function (json) { + $("#add-deliverables").find(".error").remove(); + $("#list-deliverables").find(".deliverables").remove(); + $("#list-deliverables").find(".total").remove(); + var deliverables = $(''); + var deliverable_items = json.deliverables; + $.each(deliverable_items, function (i) { + var url = + "/api/v1/projects/" + + deliverable_items[i]["project_id"] + + "/invoices/" + + deliverable_items[i]["invoice_id"] + + "/deliverables/"; + var deliverable = $( + "" + + deliverable_items[i]["deliverable"]["name"] + + " (" + + deliverable_items[i]["quantity"] + + " $" + + deliverable_items[i]["deliverable"]["unit_price"] + + ') Remove' + + json.responseJSON.detail + + "
" + ); + $("#add-deliverables").append(errorText); + }, }); + }); })(jQuery); diff --git a/hypha/static_src/javascript/determination-template.js b/hypha/static_src/javascript/determination-template.js index fb3d6a4d76..f42ec90aa0 100644 --- a/hypha/static_src/javascript/determination-template.js +++ b/hypha/static_src/javascript/determination-template.js @@ -1,75 +1,75 @@ (function () { - const field_blocks_ids = JSON.parse( - document.getElementById("block-ids").textContent - ); + const field_blocks_ids = JSON.parse( + document.getElementById("block-ids").textContent + ); - let DeterminationCopy = class { - static selector() { - return "#id_" + field_blocks_ids["determination"]; - } + let DeterminationCopy = class { + static selector() { + return "#id_" + field_blocks_ids["determination"]; + } - constructor(node) { - this.node = node; - this.bindEventListeners(); - } + constructor(node) { + this.node = node; + this.bindEventListeners(); + } - bindEventListeners() { - this.node.addEventListener( - "change", - (e) => { - this.getMatchingCopy(e.target.value); - }, - false - ); - } + bindEventListeners() { + this.node.addEventListener( + "change", + (e) => { + this.getMatchingCopy(e.target.value); + }, + false + ); + } - getMatchingCopy(value) { - const proposal_form = document.querySelector("#id_proposal_form"); - if (value === "0") { - this.text = document.querySelector( - 'div[data-type="rejected"]' - ).textContent; - if (proposal_form) { - proposal_form.disabled = true; - proposal_form.required = false; - } - } else if (value === "1") { - this.text = document.querySelector( - 'div[data-type="more_info"]' - ).textContent; - if (proposal_form) { - proposal_form.disabled = true; - proposal_form.required = false; - } - } else { - this.text = document.querySelector( - 'div[data-type="accepted"]' - ).textContent; - if (proposal_form) { - proposal_form.disabled = false; - proposal_form.required = true; - } - } - this.updateTextArea(this.text); + getMatchingCopy(value) { + const proposal_form = document.querySelector("#id_proposal_form"); + if (value === "0") { + this.text = document.querySelector( + 'div[data-type="rejected"]' + ).textContent; + if (proposal_form) { + proposal_form.disabled = true; + proposal_form.required = false; } - - updateTextArea(text) { - this.message_box = document.querySelector( - "#id_" + field_blocks_ids["message"] + "_ifr" - ); - this.message_box.contentDocument.getElementsByTagName( - "body" - )[0].innerHTML = text; + } else if (value === "1") { + this.text = document.querySelector( + 'div[data-type="more_info"]' + ).textContent; + if (proposal_form) { + proposal_form.disabled = true; + proposal_form.required = false; } - }; - - document.querySelectorAll(DeterminationCopy.selector()).forEach((el) => { - new DeterminationCopy(el); - }); - window.addEventListener("load", function (event) { - const proposal_form_field = document.querySelector("#id_proposal_form"); - if (proposal_form_field && !proposal_form_field.value) { - proposal_form_field.disabled = true; + } else { + this.text = document.querySelector( + 'div[data-type="accepted"]' + ).textContent; + if (proposal_form) { + proposal_form.disabled = false; + proposal_form.required = true; } - }); + } + this.updateTextArea(this.text); + } + + updateTextArea(text) { + this.message_box = document.querySelector( + "#id_" + field_blocks_ids["message"] + "_ifr" + ); + this.message_box.contentDocument.getElementsByTagName( + "body" + )[0].innerHTML = text; + } + }; + + document.querySelectorAll(DeterminationCopy.selector()).forEach((el) => { + new DeterminationCopy(el); + }); + window.addEventListener("load", function (event) { + const proposal_form_field = document.querySelector("#id_proposal_form"); + if (proposal_form_field && !proposal_form_field.value) { + proposal_form_field.disabled = true; + } + }); })(); diff --git a/hypha/static_src/javascript/document-category.js b/hypha/static_src/javascript/document-category.js index 4694de467f..11b7fb6a79 100644 --- a/hypha/static_src/javascript/document-category.js +++ b/hypha/static_src/javascript/document-category.js @@ -4,7 +4,6 @@ */ // eslint-disable-next-line no-unused-vars function handleCategory(category) { - document.getElementById("id_category").value = category; - document.getElementsByClassName("form__group id_category")[0].hidden = - "true"; + document.getElementById("id_category").value = category; + document.getElementsByClassName("form__group id_category")[0].hidden = "true"; } diff --git a/hypha/static_src/javascript/file-uploads.js b/hypha/static_src/javascript/file-uploads.js index 6de44b1659..2d3ce2d6e1 100644 --- a/hypha/static_src/javascript/file-uploads.js +++ b/hypha/static_src/javascript/file-uploads.js @@ -1,34 +1,29 @@ document.addEventListener("DOMContentLoaded", function () { - // Initialize django-file-form - document.querySelectorAll("form").forEach(function (form) { - // Prevent initializing it multiple times and run it for forms - // that have a `form_id` field added by django-file-form. - if ( - !form.initUploadFieldsDone && - form.querySelector("[name=form_id]") - ) { - init(form); - form.initUploadFieldsDone = true; - } - }); + // Initialize django-file-form + document.querySelectorAll("form").forEach(function (form) { + // Prevent initializing it multiple times and run it for forms + // that have a `form_id` field added by django-file-form. + if (!form.initUploadFieldsDone && form.querySelector("[name=form_id]")) { + init(form); + form.initUploadFieldsDone = true; + } + }); - /** - * Initialize django-file-form for a form. - * @param {object} form The form to initialize. - */ - function init(form) { - if (document.querySelectorAll(".form__group--file").length) { - window.initUploadFields(form); + /** + * Initialize django-file-form for a form. + * @param {object} form The form to initialize. + */ + function init(form) { + if (document.querySelectorAll(".form__group--file").length) { + window.initUploadFields(form); - // Hide wrapper elements for hidden inputs added by django-file-form - document - .querySelectorAll("input[type=hidden]") - .forEach(function (input) { - var closestFormGroup = input.closest(".form__group"); - if (closestFormGroup) { - closestFormGroup.hidden = true; - } - }); + // Hide wrapper elements for hidden inputs added by django-file-form + document.querySelectorAll("input[type=hidden]").forEach(function (input) { + var closestFormGroup = input.closest(".form__group"); + if (closestFormGroup) { + closestFormGroup.hidden = true; } + }); } + } }); diff --git a/hypha/static_src/javascript/form-group-toggle.js b/hypha/static_src/javascript/form-group-toggle.js index 2f0ea92d05..6c27c1ac48 100644 --- a/hypha/static_src/javascript/form-group-toggle.js +++ b/hypha/static_src/javascript/form-group-toggle.js @@ -1,57 +1,48 @@ /* eslint-disable no-loop-func */ (function ($) { - var i; - for (i = 2; i < 20; i++) { - var $field_group = $(".field-group-" + i); - if ($field_group.length) { - var classes = "field-group-wrapper field-group-wrapper-" + i; - $field_group.each(function () { - if ( - $(this).data("hidden") && - classes.indexOf("js-hidden") === -1 - ) { - classes += " js-hidden"; - } - }); - $field_group.wrapAll(''); - } else { - break; + var i; + for (i = 2; i < 20; i++) { + var $field_group = $(".field-group-" + i); + if ($field_group.length) { + var classes = "field-group-wrapper field-group-wrapper-" + i; + $field_group.each(function () { + if ($(this).data("hidden") && classes.indexOf("js-hidden") === -1) { + classes += " js-hidden"; } + }); + $field_group.wrapAll(''); + } else { + break; } + } - $('.form-fields-grouper input[type="radio"]').on("change", function () { - var radio_input_value = $(this).val(); - var fields_grouper_div = this.closest(".form-fields-grouper"); - var fields_grouper_for = $(fields_grouper_div).data("grouper-for"); - var group_toggle_on_value = $(fields_grouper_div).data("toggle-on"); - var group_toggle_off_value = $(fields_grouper_div).data("toggle-off"); + $('.form-fields-grouper input[type="radio"]').on("change", function () { + var radio_input_value = $(this).val(); + var fields_grouper_div = this.closest(".form-fields-grouper"); + var fields_grouper_for = $(fields_grouper_div).data("grouper-for"); + var group_toggle_on_value = $(fields_grouper_div).data("toggle-on"); + var group_toggle_off_value = $(fields_grouper_div).data("toggle-off"); - if (radio_input_value === group_toggle_on_value) { - $(".field-group-wrapper-" + fields_grouper_for) - .removeClass("js-hidden") - .addClass("highlighted"); - $(".field-group-" + fields_grouper_for).each(function () { - if ($(this).data("required") === "True") { - $(this) - .children(".form__item") - .children() - .attr("required", true); - $(this) - .children("label") - .append('*'); - } - }); - } else if (radio_input_value === group_toggle_off_value) { - $(".field-group-wrapper-" + fields_grouper_for) - .removeClass("highlighted") - .addClass("js-hidden"); - $(".field-group-" + fields_grouper_for).each(function () { - $(this) - .children(".form__item") - .children() - .attr("required", false); - $(this).children("label").children(".form__required").remove(); - }); + if (radio_input_value === group_toggle_on_value) { + $(".field-group-wrapper-" + fields_grouper_for) + .removeClass("js-hidden") + .addClass("highlighted"); + $(".field-group-" + fields_grouper_for).each(function () { + if ($(this).data("required") === "True") { + $(this).children(".form__item").children().attr("required", true); + $(this) + .children("label") + .append('*'); } - }); + }); + } else if (radio_input_value === group_toggle_off_value) { + $(".field-group-wrapper-" + fields_grouper_for) + .removeClass("highlighted") + .addClass("js-hidden"); + $(".field-group-" + fields_grouper_for).each(function () { + $(this).children(".form__item").children().attr("required", false); + $(this).children("label").children(".form__required").remove(); + }); + } + }); })(jQuery); diff --git a/hypha/static_src/javascript/multi-input-fields.js b/hypha/static_src/javascript/multi-input-fields.js index 651905e43a..cd806bb7c1 100644 --- a/hypha/static_src/javascript/multi-input-fields.js +++ b/hypha/static_src/javascript/multi-input-fields.js @@ -1,44 +1,42 @@ (function ($) { - // Visibility Index is set to 0 initially in the backend. But in case of edit application forms - // with multiple values already set, we need to update it. The visibility index helps - // to get the next field from the list of hidden inputs to be shown to an applicant on clicking the add button. - // For example, a total of 5 multiple inputs, 3 values are already set by applicant while creating a submission. - // On edit form, the visibility index should be updates so when the user clicks add, the 4th input should be displayed. - $(".multi-input-add-btn").each(function () { - var multiFieldId = $(this).data("multi-field-id"); - const multiMaxIndex = $(this).data("multi-max-index"); - var multiFieldInputs = $( - ".form__item[data-multi-field-for='" + multiFieldId + "']" - ); - var multiFieldHiddenInput = $( - ".form__item.multi-input-field-hidden[data-multi-field-for='" + - multiFieldId + - "']" - ); - var multiVisibilityIndex = multiFieldInputs.index( - multiFieldHiddenInput - ); - if (multiVisibilityIndex >= 0) { - $(this).data("multi-visibility-index", multiVisibilityIndex); - } else if (multiVisibilityIndex === -1) { - $(this).data("multi-visibility-index", multiMaxIndex); - } - }); + // Visibility Index is set to 0 initially in the backend. But in case of edit application forms + // with multiple values already set, we need to update it. The visibility index helps + // to get the next field from the list of hidden inputs to be shown to an applicant on clicking the add button. + // For example, a total of 5 multiple inputs, 3 values are already set by applicant while creating a submission. + // On edit form, the visibility index should be updates so when the user clicks add, the 4th input should be displayed. + $(".multi-input-add-btn").each(function () { + var multiFieldId = $(this).data("multi-field-id"); + const multiMaxIndex = $(this).data("multi-max-index"); + var multiFieldInputs = $( + ".form__item[data-multi-field-for='" + multiFieldId + "']" + ); + var multiFieldHiddenInput = $( + ".form__item.multi-input-field-hidden[data-multi-field-for='" + + multiFieldId + + "']" + ); + var multiVisibilityIndex = multiFieldInputs.index(multiFieldHiddenInput); + if (multiVisibilityIndex >= 0) { + $(this).data("multi-visibility-index", multiVisibilityIndex); + } else if (multiVisibilityIndex === -1) { + $(this).data("multi-visibility-index", multiMaxIndex); + } + }); - $(".multi-input-add-btn").click(function () { - var multiFieldId = $(this).data("multi-field-id"); - var multiVisibilityIndex = $(this).data("multi-visibility-index"); - const multiMaxIndex = $(this).data("multi-max-index"); + $(".multi-input-add-btn").click(function () { + var multiFieldId = $(this).data("multi-field-id"); + var multiVisibilityIndex = $(this).data("multi-visibility-index"); + const multiMaxIndex = $(this).data("multi-max-index"); - var multiShowIndex = multiVisibilityIndex + 1; - if (multiShowIndex <= multiMaxIndex) { - var multiShowId = "id_" + multiFieldId + "_" + multiShowIndex; - $("#" + multiShowId) - .parent(".form__item") - .removeClass("multi-input-field-hidden"); - $(this).data("multi-visibility-index", multiShowIndex); - } else { - $(this).hide(); - } - }); + var multiShowIndex = multiVisibilityIndex + 1; + if (multiShowIndex <= multiMaxIndex) { + var multiShowId = "id_" + multiFieldId + "_" + multiShowIndex; + $("#" + multiShowId) + .parent(".form__item") + .removeClass("multi-input-field-hidden"); + $(this).data("multi-visibility-index", multiShowIndex); + } else { + $(this).hide(); + } + }); })(jQuery); diff --git a/hypha/static_src/javascript/past-reports-pagination.js b/hypha/static_src/javascript/past-reports-pagination.js index 9df1a32bcc..9fd0197db8 100644 --- a/hypha/static_src/javascript/past-reports-pagination.js +++ b/hypha/static_src/javascript/past-reports-pagination.js @@ -1,35 +1,32 @@ (function ($) { - /** - * This script is used to paginate the past reports table. - */ - function pastReportsPagination() { - $(".js-data-block-pagination").click((e) => { - e.preventDefault(); - showNextTen(); - }); - } + /** + * This script is used to paginate the past reports table. + */ + function pastReportsPagination() { + $(".js-data-block-pagination").click((e) => { + e.preventDefault(); + showNextTen(); + }); + } - /** - * Show next ten. - */ - function showNextTen() { - const [...nextTen] = $(".js-past-reports-table tr.is-hidden").slice( - 0, - 10 - ); - nextTen.forEach((item) => item.classList.remove("is-hidden")); - checkRemaining(); - } + /** + * Show next ten. + */ + function showNextTen() { + const [...nextTen] = $(".js-past-reports-table tr.is-hidden").slice(0, 10); + nextTen.forEach((item) => item.classList.remove("is-hidden")); + checkRemaining(); + } - /** - * Check remaning. - */ - function checkRemaining() { - const [...remaining] = $(".js-past-reports-table tr.is-hidden"); - if (remaining.length === 0) { - $(".js-data-block-pagination").addClass("is-hidden"); - } + /** + * Check remaning. + */ + function checkRemaining() { + const [...remaining] = $(".js-past-reports-table tr.is-hidden"); + if (remaining.length === 0) { + $(".js-data-block-pagination").addClass("is-hidden"); } + } - pastReportsPagination(); + pastReportsPagination(); })(jQuery); diff --git a/hypha/static_src/javascript/report-calculator.js b/hypha/static_src/javascript/report-calculator.js index abe2ebb30d..63ba3665ad 100644 --- a/hypha/static_src/javascript/report-calculator.js +++ b/hypha/static_src/javascript/report-calculator.js @@ -1,162 +1,157 @@ document.addEventListener("htmx:afterRequest", function () { - const reportDataEl = document.getElementById("reportData"); - if (!reportDataEl) { - return; - } - const reportData = JSON.parse(reportDataEl.textContent); - - // Form inputs - const frequencyNumberInput = document.getElementById("id_occurrence"); - const frequencyPeriodSelect = document.getElementById("id_frequency"); - const startDateInput = document.getElementById("id_start"); - - // Form slots - const projectEndSlot = document.querySelector(".js-project-end-slot"); - const frequencyNumberSlot = document.querySelector( - ".js-frequency-number-slot" - ); - const frequencyPeriodSlot = document.querySelector( - ".js-frequency-period-slot" - ); - const periodStartSlot = document.querySelector(".js-report-period-start"); - const periodEndSlot = document.querySelector(".js-report-period-end"); - const nextReportDueSlot = document.querySelector( - ".js-next-report-due-slot" - ); - - /** - * Set initial values & setup event listeners - */ - function init() { - // Set on page load - setProjectEnd(); - setFrequency(); - setReportPeriodStart(); - setReportPeriod(); - - // Add event listeners - addFrequencyEvents(); - addReportPeriodEvents(); - } - - /** - * Sets the project end date in the form info box - */ - function setProjectEnd() { - projectEndSlot.innerHTML = reportData.projectEndDate; - } - - /** - * Set the reporting frequency - */ - function setFrequency() { - frequencyPeriodSlot.innerHTML = `${frequencyPeriodSlot.value}`; - frequencyNumberSlot.innerHTML = frequencyNumberInput.value; - pluraliseTimePeriod(frequencyNumberInput.value); - } - - /** - * Set the reporting period start date - */ - function setReportPeriodStart() { - const startDate = new Date(reportData.startDate); - periodStartSlot.innerHTML = startDate.toISOString().slice(0, 10); - } - - /** - * Set the reporting period - */ - function setReportPeriod() { - // Update the reporting period end date (next report date) - periodEndSlot.innerHTML = startDateInput.value; - - // Update the reporting period range (next report date - today) - const daysDiff = dateDiffInDays( - new Date(), - new Date(startDateInput.value) - ); - const weeksAndDays = getWeeks(daysDiff); - const { weeks, days } = weeksAndDays; - const pluraliseWeeks = weeks === 1 ? "" : "s"; - const pluraliseDays = days === 1 ? "" : "s"; - - nextReportDueSlot.innerHTML = ` + const reportDataEl = document.getElementById("reportData"); + if (!reportDataEl) { + return; + } + const reportData = JSON.parse(reportDataEl.textContent); + + // Form inputs + const frequencyNumberInput = document.getElementById("id_occurrence"); + const frequencyPeriodSelect = document.getElementById("id_frequency"); + const startDateInput = document.getElementById("id_start"); + + // Form slots + const projectEndSlot = document.querySelector(".js-project-end-slot"); + const frequencyNumberSlot = document.querySelector( + ".js-frequency-number-slot" + ); + const frequencyPeriodSlot = document.querySelector( + ".js-frequency-period-slot" + ); + const periodStartSlot = document.querySelector(".js-report-period-start"); + const periodEndSlot = document.querySelector(".js-report-period-end"); + const nextReportDueSlot = document.querySelector(".js-next-report-due-slot"); + + /** + * Set initial values & setup event listeners + */ + function init() { + // Set on page load + setProjectEnd(); + setFrequency(); + setReportPeriodStart(); + setReportPeriod(); + + // Add event listeners + addFrequencyEvents(); + addReportPeriodEvents(); + } + + /** + * Sets the project end date in the form info box + */ + function setProjectEnd() { + projectEndSlot.innerHTML = reportData.projectEndDate; + } + + /** + * Set the reporting frequency + */ + function setFrequency() { + frequencyPeriodSlot.innerHTML = `${frequencyPeriodSlot.value}`; + frequencyNumberSlot.innerHTML = frequencyNumberInput.value; + pluraliseTimePeriod(frequencyNumberInput.value); + } + + /** + * Set the reporting period start date + */ + function setReportPeriodStart() { + const startDate = new Date(reportData.startDate); + periodStartSlot.innerHTML = startDate.toISOString().slice(0, 10); + } + + /** + * Set the reporting period + */ + function setReportPeriod() { + // Update the reporting period end date (next report date) + periodEndSlot.innerHTML = startDateInput.value; + + // Update the reporting period range (next report date - today) + const daysDiff = dateDiffInDays(new Date(), new Date(startDateInput.value)); + const weeksAndDays = getWeeks(daysDiff); + const { weeks, days } = weeksAndDays; + const pluraliseWeeks = weeks === 1 ? "" : "s"; + const pluraliseDays = days === 1 ? "" : "s"; + + nextReportDueSlot.innerHTML = ` ${ - weeks > 0 ? `${weeks} week${pluraliseWeeks}` : "" + weeks > 0 ? `${weeks} week${pluraliseWeeks}` : "" } ${days} day${pluraliseDays} `; - } - - /** - * Set report period once start date receives input - */ - function addReportPeriodEvents() { - startDateInput.addEventListener("input", () => { - setReportPeriod(); - }); - } - - /** - * Update reporting frequency as the options are changed - */ - function addFrequencyEvents() { - frequencyNumberInput.addEventListener("input", () => { - setFrequency(); - }); - - frequencyPeriodSelect.addEventListener("change", () => { - setFrequency(); - }); - } - - /** - * Adds an "s" to the frequencyPeriodSelect text if plural, removes "s" otherwise. - * - * @param {number} number - number to determine plural for - */ - function pluraliseTimePeriod(number) { - frequencyPeriodSlot.innerHTML = `${frequencyPeriodSelect.value}${ - Number(number) === 1 ? "" : "s" - }`; - } - - /** - * Get the difference of days between two dates - * - * @param {Date} startDate - the subtrahend date - * @param {Date} endDate - the minuend date - * - * @returns {number} Difference of days betwen the given dates - */ - function dateDiffInDays(startDate, endDate) { - const msPerDay = 1000 * 60 * 60 * 24; - const utc1 = Date.UTC( - startDate.getFullYear(), - startDate.getMonth(), - startDate.getDate() - ); - const utc2 = Date.UTC( - endDate.getFullYear(), - endDate.getMonth(), - endDate.getDate() - ); - - return Math.floor((utc2 - utc1) / msPerDay); - } - - /** - * Convert days into weeks and days - * - * @param {number} days - number of days - * - * @returns {{weeks: number, days: number}} number of weeks & days - */ - function getWeeks(days) { - return { - weeks: Math.floor(days / 7), - days: days % 7, - }; - } - - init(); + } + + /** + * Set report period once start date receives input + */ + function addReportPeriodEvents() { + startDateInput.addEventListener("input", () => { + setReportPeriod(); + }); + } + + /** + * Update reporting frequency as the options are changed + */ + function addFrequencyEvents() { + frequencyNumberInput.addEventListener("input", () => { + setFrequency(); + }); + + frequencyPeriodSelect.addEventListener("change", () => { + setFrequency(); + }); + } + + /** + * Adds an "s" to the frequencyPeriodSelect text if plural, removes "s" otherwise. + * + * @param {number} number - number to determine plural for + */ + function pluraliseTimePeriod(number) { + frequencyPeriodSlot.innerHTML = `${frequencyPeriodSelect.value}${ + Number(number) === 1 ? "" : "s" + }`; + } + + /** + * Get the difference of days between two dates + * + * @param {Date} startDate - the subtrahend date + * @param {Date} endDate - the minuend date + * + * @returns {number} Difference of days betwen the given dates + */ + function dateDiffInDays(startDate, endDate) { + const msPerDay = 1000 * 60 * 60 * 24; + const utc1 = Date.UTC( + startDate.getFullYear(), + startDate.getMonth(), + startDate.getDate() + ); + const utc2 = Date.UTC( + endDate.getFullYear(), + endDate.getMonth(), + endDate.getDate() + ); + + return Math.floor((utc2 - utc1) / msPerDay); + } + + /** + * Convert days into weeks and days + * + * @param {number} days - number of days + * + * @returns {{weeks: number, days: number}} number of weeks & days + */ + function getWeeks(days) { + return { + weeks: Math.floor(days / 7), + days: days % 7, + }; + } + + init(); }); diff --git a/hypha/static_src/javascript/review-form-actions.js b/hypha/static_src/javascript/review-form-actions.js index f8b4fda8cb..4aff1dc33a 100644 --- a/hypha/static_src/javascript/review-form-actions.js +++ b/hypha/static_src/javascript/review-form-actions.js @@ -1,30 +1,30 @@ (function () { - /** - * Show dialog if user have changed the form and not saved. - * @param {object} f - form element - * @returns {object} - form contents - */ - function formContents(f) { - // Thanks to https://stackoverflow.com/a/44033425 - return Array.from(new FormData(f), function (e) { - return e.map(encodeURIComponent).join("="); - }).join("&"); - } + /** + * Show dialog if user have changed the form and not saved. + * @param {object} f - form element + * @returns {object} - form contents + */ + function formContents(f) { + // Thanks to https://stackoverflow.com/a/44033425 + return Array.from(new FormData(f), function (e) { + return e.map(encodeURIComponent).join("="); + }).join("&"); + } - // Show dialog if user have changed the form and not saved. - document.addEventListener("DOMContentLoaded", function () { - const form = document.querySelector("#review-form-edit"); - const original = formContents(form); + // Show dialog if user have changed the form and not saved. + document.addEventListener("DOMContentLoaded", function () { + const form = document.querySelector("#review-form-edit"); + const original = formContents(form); - window.onbeforeunload = function () { - const formNow = formContents(form); - if (formNow !== original) { - return false; - } - }; + window.onbeforeunload = function () { + const formNow = formContents(form); + if (formNow !== original) { + return false; + } + }; - form.addEventListener("submit", function () { - window.onbeforeunload = null; - }); + form.addEventListener("submit", function () { + window.onbeforeunload = null; }); + }); })(); diff --git a/hypha/static_src/javascript/submission-filters.js b/hypha/static_src/javascript/submission-filters.js index 8509579d8c..e75deeb3e1 100644 --- a/hypha/static_src/javascript/submission-filters.js +++ b/hypha/static_src/javascript/submission-filters.js @@ -1,197 +1,185 @@ (function ($) { - // Variables - const $toggleButton = $(".js-toggle-filters"); - const $closeButton = $(".js-close-filters"); - const $clearButton = $(".js-clear-filters"); - const filterOpenClass = "filters-open"; - const filterActiveClass = "is-active"; - - const urlParams = new URLSearchParams(window.location.search); - - const persistedParams = ["sort", "query", "submission"]; + // Variables + const $toggleButton = $(".js-toggle-filters"); + const $closeButton = $(".js-close-filters"); + const $clearButton = $(".js-clear-filters"); + const filterOpenClass = "filters-open"; + const filterActiveClass = "is-active"; + + const urlParams = new URLSearchParams(window.location.search); + + const persistedParams = ["sort", "query", "submission"]; + + // check if the page has a query string and keep filters open if so on desktop + const minimumNumberParams = persistedParams.reduce( + (count, param) => (count + urlParams.has(param) ? 1 : 0), + 0 + ); + + if ([...urlParams].length > minimumNumberParams && $(window).width() > 1024) { + $(".filters").addClass(filterOpenClass); + $(".js-toggle-filters").text("Clear filters"); + } + + // Add active class to filters - dropdowns are dynamically appended to the dom, + // so we have to listen for the event higher up + $("body").on("click", ".select2-dropdown", (e) => { + // get the id of the dropdown + let selectId = e.target.parentElement.parentElement.id; + + // find the matching dropdown + let match = $(`.select2-selection[aria-owns="${selectId}"]`); + + if (match.length !== 0) { + // if the dropdown contains a clear class, the filters are active + if ($(match[0]).find("span.select2-selection__clear").length !== 0) { + match[0].classList.add(filterActiveClass); + } else { + match[0].classList.remove(filterActiveClass); + } + } + }); - // check if the page has a query string and keep filters open if so on desktop - const minimumNumberParams = persistedParams.reduce( - (count, param) => (count + urlParams.has(param) ? 1 : 0), - 0 + // remove active class on clearing select2 + $(".select2").on("select2:unselecting", (e) => { + const dropdown = e.target.nextElementSibling.firstChild.firstChild; + if (dropdown.classList.contains(filterActiveClass)) { + dropdown.classList.remove(filterActiveClass); + } + }); + + // toggle filters + $toggleButton.on("click", (e) => { + // find the nearest filters + const filters = e.target.closest(".js-table-actions").nextElementSibling; + + if (filters.classList.contains(filterOpenClass)) { + handleClearFilters(); + } else { + filters.classList.add(filterOpenClass); + // only update button text on desktop + if (window.innerWidth >= 1024) { + updateButtonText(e.target, filters); + } + } + }); + + // close filters on mobile + $closeButton.on("click", (e) => { + e.target.closest(".filters").classList.remove(filterOpenClass); + }); + + /** + * Redirect to submissions home to clear filters. + */ + function handleClearFilters() { + const query = persistedParams.reduce( + (query, param) => + query + + (urlParams.get(param) ? `&${param}=${urlParams.get(param)}` : ""), + "?" ); + window.location.href = window.location.href.split("?")[0] + query; + } + + /** + * Toggle filters button wording. + * @param {object} button - button element + * @param {string} filters - filters element + */ + function updateButtonText(button, filters) { + if (filters.classList.contains(filterOpenClass)) { + button.textContent = "Clear filters"; + } else { + button.textContent = "Filters"; + } + } + + /** + * Corrects spacing of dropdowns when toggled on mobile. + * @param {object} element - element to adjust padding for + */ + function mobileFilterPadding(element) { + const expanded = "expanded-filter-element"; + const dropdown = $(element).closest(".select2"); + const openDropdown = $(".select2 ." + expanded); + let dropdownMargin = 0; if ( - [...urlParams].length > minimumNumberParams && - $(window).width() > 1024 + openDropdown.length > 0 && + !openDropdown.hasClass("select2-container--open") ) { - $(".filters").addClass(filterOpenClass); - $(".js-toggle-filters").text("Clear filters"); + // reset the margin of the select we previously worked + openDropdown.removeClass(expanded); + // store the offset to adjust the new select box (elements above the old dropdown unaffected) + if (dropdown.position().top > openDropdown.position().top) { + dropdownMargin = parseInt(openDropdown.css("marginBottom")); + } + openDropdown.css("margin-bottom", "0px"); } - // Add active class to filters - dropdowns are dynamically appended to the dom, - // so we have to listen for the event higher up - $("body").on("click", ".select2-dropdown", (e) => { - // get the id of the dropdown - let selectId = e.target.parentElement.parentElement.id; - - // find the matching dropdown - let match = $(`.select2-selection[aria-owns="${selectId}"]`); - - if (match.length !== 0) { - // if the dropdown contains a clear class, the filters are active - if ( - $(match[0]).find("span.select2-selection__clear").length !== 0 - ) { - match[0].classList.add(filterActiveClass); - } else { - match[0].classList.remove(filterActiveClass); - } - } - }); - - // remove active class on clearing select2 - $(".select2").on("select2:unselecting", (e) => { - const dropdown = e.target.nextElementSibling.firstChild.firstChild; - if (dropdown.classList.contains(filterActiveClass)) { - dropdown.classList.remove(filterActiveClass); - } - }); - - // toggle filters - $toggleButton.on("click", (e) => { - // find the nearest filters - const filters = - e.target.closest(".js-table-actions").nextElementSibling; - - if (filters.classList.contains(filterOpenClass)) { - handleClearFilters(); - } else { - filters.classList.add(filterOpenClass); - // only update button text on desktop - if (window.innerWidth >= 1024) { - updateButtonText(e.target, filters); - } - } + if (dropdown.hasClass("select2-container--open")) { + dropdown.addClass(expanded); + const dropdownID = $(element) + .closest(".select2-selection") + .attr("aria-owns"); + // Element which has the height of the select dropdown + const match = $(`ul#${dropdownID}`); + const dropdownHeight = match.outerHeight(true); + + // Element which has the position of the dropdown + const positionalMatch = match.closest(".select2-container"); + + // Pad the bottom of the select box + dropdown.css("margin-bottom", `${dropdownHeight}px`); + + // bump up the dropdown options by height of closed elements + positionalMatch.css( + "top", + positionalMatch.position().top - dropdownMargin + ); + } + } + + // clear all filters + $clearButton.on("click", () => { + const dropdowns = document.querySelectorAll(".form__filters select"); + dropdowns.forEach((dropdown) => { + $(dropdown).val(null).trigger("change"); + $(".select2-selection.is-active").removeClass(filterActiveClass); + mobileFilterPadding(dropdown); }); + }); - // close filters on mobile - $closeButton.on("click", (e) => { - e.target.closest(".filters").classList.remove(filterOpenClass); + $(function () { + // Add active class to select2 checkboxes after page has been filtered + const clearButtons = document.querySelectorAll(".select2-selection__clear"); + clearButtons.forEach((clearButton) => { + clearButton.parentElement.parentElement.classList.add(filterActiveClass); }); + }); - /** - * Redirect to submissions home to clear filters. - */ - function handleClearFilters() { - const query = persistedParams.reduce( - (query, param) => - query + - (urlParams.get(param) - ? `&${param}=${urlParams.get(param)}` - : ""), - "?" - ); - window.location.href = window.location.href.split("?")[0] + query; - } - - /** - * Toggle filters button wording. - * @param {object} button - button element - * @param {string} filters - filters element - */ - function updateButtonText(button, filters) { - if (filters.classList.contains(filterOpenClass)) { - button.textContent = "Clear filters"; - } else { - button.textContent = "Filters"; - } - } + // reset mobile filters if they're open past the tablet breakpoint + $(window) + .resize(function resize() { + if ($(window).width() < 1024) { + // close the filters if open when reducing the window size + $(".filters").removeClass("filters-open"); - /** - * Corrects spacing of dropdowns when toggled on mobile. - * @param {object} element - element to adjust padding for - */ - function mobileFilterPadding(element) { - const expanded = "expanded-filter-element"; - const dropdown = $(element).closest(".select2"); - const openDropdown = $(".select2 ." + expanded); - let dropdownMargin = 0; - - if ( - openDropdown.length > 0 && - !openDropdown.hasClass("select2-container--open") - ) { - // reset the margin of the select we previously worked - openDropdown.removeClass(expanded); - // store the offset to adjust the new select box (elements above the old dropdown unaffected) - if (dropdown.position().top > openDropdown.position().top) { - dropdownMargin = parseInt(openDropdown.css("marginBottom")); - } - openDropdown.css("margin-bottom", "0px"); - } - - if (dropdown.hasClass("select2-container--open")) { - dropdown.addClass(expanded); - const dropdownID = $(element) - .closest(".select2-selection") - .attr("aria-owns"); - // Element which has the height of the select dropdown - const match = $(`ul#${dropdownID}`); - const dropdownHeight = match.outerHeight(true); - - // Element which has the position of the dropdown - const positionalMatch = match.closest(".select2-container"); - - // Pad the bottom of the select box - dropdown.css("margin-bottom", `${dropdownHeight}px`); - - // bump up the dropdown options by height of closed elements - positionalMatch.css( - "top", - positionalMatch.position().top - dropdownMargin - ); - } - } + // update filter button text + $(".js-toggle-filters").text("Filters"); - // clear all filters - $clearButton.on("click", () => { - const dropdowns = document.querySelectorAll(".form__filters select"); - dropdowns.forEach((dropdown) => { - $(dropdown).val(null).trigger("change"); - $(".select2-selection.is-active").removeClass(filterActiveClass); - mobileFilterPadding(dropdown); + // Correct spacing of dropdowns when toggled + $(".select2").on("click", (e) => { + mobileFilterPadding(e.target); }); - }); - - $(function () { - // Add active class to select2 checkboxes after page has been filtered - const clearButtons = document.querySelectorAll( - ".select2-selection__clear" - ); - clearButtons.forEach((clearButton) => { - clearButton.parentElement.parentElement.classList.add( - filterActiveClass - ); - }); - }); - - // reset mobile filters if they're open past the tablet breakpoint - $(window) - .resize(function resize() { - if ($(window).width() < 1024) { - // close the filters if open when reducing the window size - $(".filters").removeClass("filters-open"); - - // update filter button text - $(".js-toggle-filters").text("Filters"); - - // Correct spacing of dropdowns when toggled - $(".select2").on("click", (e) => { - mobileFilterPadding(e.target); - }); - } else { - $(".filters").addClass("filters-open"); - } - }) - .trigger("resize"); - - $("#show-filters-button").on("click", () => { + } else { $(".filters").addClass("filters-open"); - }); + } + }) + .trigger("resize"); + + $("#show-filters-button").on("click", () => { + $(".filters").addClass("filters-open"); + }); })(jQuery); diff --git a/hypha/static_src/javascript/submission-form-copy.js b/hypha/static_src/javascript/submission-form-copy.js index 95b5631790..546dedd58a 100644 --- a/hypha/static_src/javascript/submission-form-copy.js +++ b/hypha/static_src/javascript/submission-form-copy.js @@ -1,132 +1,128 @@ (function ($) { - /** - * Strip html tags from text. - * @param {string} html - The html - * @returns {string} The text without html tags. - */ - function strip(html) { - var doc = new DOMParser().parseFromString(html, "text/html"); - return doc.body.textContent.trim() || ""; - } + /** + * Strip html tags from text. + * @param {string} html - The html + * @returns {string} The text without html tags. + */ + function strip(html) { + var doc = new DOMParser().parseFromString(html, "text/html"); + return doc.body.textContent.trim() || ""; + } - /** - * Get all questions on the page/form. - * @returns {string} The questions and user input. - */ - function get_questions() { - var questions_text = []; - var i = 1; - questions_text.push("# " + $("h1:first").html()); - $(".application-form") - .find(".form__group, .rich-text, h2, h3") - .each(function () { - var question_text = ""; - var label_text = $(this).find(".form__question").html(); - if (label_text) { - // Get the label, i.e. question. - label_text = strip(label_text); - label_text = label_text.replace(/(\r\n|\n|\r)/gm, ""); - label_text = label_text.replace(/[ ]+/g, " "); - question_text = "### " + label_text; + /** + * Get all questions on the page/form. + * @returns {string} The questions and user input. + */ + function get_questions() { + var questions_text = []; + var i = 1; + questions_text.push("# " + $("h1:first").html()); + $(".application-form") + .find(".form__group, .rich-text, h2, h3") + .each(function () { + var question_text = ""; + var label_text = $(this).find(".form__question").html(); + if (label_text) { + // Get the label, i.e. question. + label_text = strip(label_text); + label_text = label_text.replace(/(\r\n|\n|\r)/gm, ""); + label_text = label_text.replace(/[ ]+/g, " "); + question_text = "### " + label_text; - var help_text = $(this).find(".form__help").html(); - var $help_link = $(this).find(".form__help-link"); - var word_limit = $(this).attr("data-word-limit"); - var $input_list = $(this).find(".form__item > ul > li"); - var input_text = $(this).find("input").val(); - var rich_text = $(this).find(".tinymce4-editor").val(); + var help_text = $(this).find(".form__help").html(); + var $help_link = $(this).find(".form__help-link"); + var word_limit = $(this).attr("data-word-limit"); + var $input_list = $(this).find(".form__item > ul > li"); + var input_text = $(this).find("input").val(); + var rich_text = $(this).find(".tinymce4-editor").val(); - // Get help text and link if any. - if (help_text) { - question_text = - question_text + "\n\n" + strip(help_text); - } - if ($help_link.length !== 0) { - question_text = - question_text + - "\n\n" + - strip($help_link.html()) + - " <" + - $help_link.find("a").attr("href") + - ">"; - } + // Get help text and link if any. + if (help_text) { + question_text = question_text + "\n\n" + strip(help_text); + } + if ($help_link.length !== 0) { + question_text = + question_text + + "\n\n" + + strip($help_link.html()) + + " <" + + $help_link.find("a").attr("href") + + ">"; + } - if (word_limit) { - question_text = - question_text + - "\n\nLimit this field to " + - word_limit + - " words."; - } + if (word_limit) { + question_text = + question_text + + "\n\nLimit this field to " + + word_limit + + " words."; + } - // Get the user input if any. - if ($input_list.length !== 0) { - var input_list = []; - var input_item = ""; - $input_list.each(function () { - input_item = strip($(this).html()); - if ($(this).find("input").is(":checked")) { - input_item = input_item + " (selected)"; - } - input_list.push(input_item); - }); - question_text = - question_text + "\n\n" + input_list.join("\n"); - } else if (input_text) { - question_text = - question_text + "\n\n" + strip(input_text); - } else if (rich_text) { - question_text = - question_text + "\n\n" + strip(rich_text); - } - } else { - // Get the sub headers and help text. - question_text = strip($(this).html()); - if ($(this).find("h2, h3")) { - question_text = "## " + i + ". " + question_text; - i++; - } - } - questions_text.push(question_text); + // Get the user input if any. + if ($input_list.length !== 0) { + var input_list = []; + var input_item = ""; + $input_list.each(function () { + input_item = strip($(this).html()); + if ($(this).find("input").is(":checked")) { + input_item = input_item + " (selected)"; + } + input_list.push(input_item); }); - return questions_text.join("\n\n"); - } + question_text = question_text + "\n\n" + input_list.join("\n"); + } else if (input_text) { + question_text = question_text + "\n\n" + strip(input_text); + } else if (rich_text) { + question_text = question_text + "\n\n" + strip(rich_text); + } + } else { + // Get the sub headers and help text. + question_text = strip($(this).html()); + if ($(this).find("h2, h3")) { + question_text = "## " + i + ". " + question_text; + i++; + } + } + questions_text.push(question_text); + }); + return questions_text.join("\n\n"); + } - // Allow users to copy all questions to the clipboard. - if ( - document.queryCommandSupported && - document.queryCommandSupported("copy") - ) { - var $button = $("") - .text("Copy questions to clipboard") - .addClass( - "button button--primary button--narrow my-2 js-clipboard-button" - ) - .attr( - "title", - "Copies all the questions and user input to the clipboard in plain text." - ); - var $application_form = $(".application-form"); - $button - .clone() - .css({ display: "block", "margin-left": "auto" }) - .insertBefore($application_form); - $button.insertAfter($application_form.find("button").last()); + // Allow users to copy all questions to the clipboard. + if ( + document.queryCommandSupported && + document.queryCommandSupported("copy") + ) { + var $button = $("") + .text("Copy questions to clipboard") + .addClass( + "button button--primary button--narrow my-2 js-clipboard-button" + ) + .attr( + "title", + "Copies all the questions and user input to the clipboard in plain text." + ); + var $application_form = $(".application-form"); + $button + .clone() + .css({ display: "block", "margin-left": "auto" }) + .insertBefore($application_form); + $button.insertAfter($application_form.find("button").last()); - $(".js-clipboard-button").on("click", function (e) { - e.preventDefault(); - $application_form.addClass("flash-item"); - var questions = get_questions(); - var $textarea = $("