Skip to content

Commit 209a3eb

Browse files
author
aDramaQueen
committed
Updated JavaScript
Added documentation. Added new property for settings: credentials.
1 parent ca1fa95 commit 209a3eb

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

bootstrap_modal_forms/static/js/bootstrap5.modal.forms.js

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
'use strict';
12
/*
23
django-bootstrap-modal-forms
34
version : 2.2.1
45
Copyright (c) 2023 Marcel Rupp
56
*/
67

7-
// Open modal & load the form at formURL to the modalContent element
8+
/**
9+
* Open modal & load the form as inner HTML from "formURL" to the "modalContent" element
10+
*
11+
* @param {Object} settings Configuration/Settings for associated modal
12+
*/
813
const modalFormCallback = function (settings) {
914
let modal = document.querySelector(settings.modalID);
1015
let content = modal.querySelector(settings.modalContent);
@@ -17,20 +22,31 @@ const modalFormCallback = function (settings) {
1722
}
1823

1924
fetch(settings.formURL).then(res => {
25+
// Get content from target URL
2026
return res.text();
2127
}).then(data => {
28+
// Set content to inner HTML
2229
content.innerHTML = data;
2330
}).then(() => {
31+
// Finally show the modal with new content
2432
modalInstance.show();
2533

2634
let form = modal.querySelector(settings.modalForm);
2735
if (form) {
2836
form.action = settings.formURL;
29-
addEventHandlers(modal, form, settings)
37+
// Add handler for form validation
38+
addEventHandlers(modal, form, settings);
3039
}
3140
});
3241
};
3342

43+
/**
44+
* Adds event handler for form validation cycle.
45+
*
46+
* @param {HTMLElement} modal The modal
47+
* @param {HTMLElement} form The actual form, that should be evaluated by the server
48+
* @param {Object} settings Configuration/Settings for associated modal
49+
*/
3450
const addEventHandlers = function (modal, form, settings) {
3551
form.addEventListener('submit', (event) => {
3652
if (settings.isDeleteForm === false) {
@@ -40,31 +56,41 @@ const addEventHandlers = function (modal, form, settings) {
4056
}
4157
});
4258

43-
modal.addEventListener('hidden.bs.modal', (event) => {
59+
modal.addEventListener('hidden.bs.modal', () => {
4460
let content = modal.querySelector(settings.modalContent);
4561
while (content.lastChild) {
4662
content.removeChild(content.lastChild);
4763
}
4864
});
4965
};
5066

51-
// Check if form.is_valid() & either show errors or submit it via callback
67+
/**
68+
* Sends the form to the server & processes the result. If the form is valid the redirect from the
69+
* form will be executed. If the form is invalid the errors are shown and no redirect will be executed.
70+
*
71+
* @param {Object} settings Configuration/Settings for associated modal
72+
* @param {Function} callback Callback to break out of form validation cycle
73+
*/
5274
const isFormValid = function (settings, callback) {
5375
let modal = document.querySelector(settings.modalID);
5476
let form = modal.querySelector(settings.modalForm);
55-
const headers = new Headers();
77+
let headers = new Headers();
5678
headers.append('X-Requested-With', 'XMLHttpRequest');
5779

5880
let btnSubmit = modal.querySelector('button[type="submit"]');
5981
btnSubmit.disabled = true;
82+
6083
fetch(form.action, {
6184
headers: headers,
6285
method: form.method,
6386
body: new FormData(form),
87+
credentials: settings.credentials,
6488
}).then(res => {
6589
return res.text();
6690
}).then(data => {
91+
console.log(data)
6792
if (data.includes(settings.errorClass)) {
93+
// Form is invalid, therefore set the returned form (with marked invalid fields) to new inner HTML
6894
modal.querySelector(settings.modalContent).innerHTML = data;
6995

7096
form = modal.querySelector(settings.modalForm);
@@ -73,6 +99,7 @@ const isFormValid = function (settings, callback) {
7399
return;
74100
}
75101

102+
// Start from the beginning
76103
form.action = settings.formURL;
77104
addEventHandlers(modal, form, settings)
78105
} else {
@@ -81,15 +108,19 @@ const isFormValid = function (settings, callback) {
81108
});
82109
};
83110

84-
// Submit form callback function
111+
/**
112+
* Submit form callback function
113+
*
114+
* @param {Object} settings Configuration/Settings for associated modal
115+
*/
85116
const submitForm = function (settings) {
86117
let modal = document.querySelector(settings.modalID);
87118
let form = modal.querySelector(settings.modalForm);
88119

89120
if (!settings.asyncUpdate) {
90121
form.submit();
91122
} else {
92-
let asyncSettingsValid = validateAsyncSettings(settings.asyncSettings);
123+
const asyncSettingsValid = validateAsyncSettings(settings.asyncSettings);
93124
if (asyncSettingsValid) {
94125
let asyncSettings = settings.asyncSettings;
95126
// Serialize form data
@@ -155,9 +186,14 @@ const submitForm = function (settings) {
155186
}
156187
};
157188

189+
/**
190+
* Validates given settings/configuration for asynchronous calls.
191+
*
192+
* @param {Object} settings Configuration/Settings for associated modal
193+
* @return {boolean} True if given configuration/settings is valid, false otherwise
194+
*/
158195
const validateAsyncSettings = function (settings) {
159-
console.log(settings)
160-
var missingSettings = [];
196+
let missingSettings = [];
161197

162198
if (!settings.successMessage) {
163199
missingSettings.push("successMessage");
@@ -179,15 +215,23 @@ const validateAsyncSettings = function (settings) {
179215
missingSettings.push("addModalFormFunction");
180216
console.error("django-bootstrap-modal-forms: 'addModalFormFunction' in asyncSettings is missing.");
181217
}
182-
183-
if (missingSettings.length > 0) {
184-
return false;
185-
}
186-
187-
return true;
218+
return missingSettings.length < 1;
188219
};
189220

190-
const modalForm = function(elem, options) {
221+
/**
222+
* Adds click listener to given button. If button is clicked, associated
223+
* modal makes a call to given URL("formURL") to load its inner HTML.
224+
*
225+
* credentials:
226+
* Prevent browser to share credentials (Cookies, Authorization headers & TLS client certificates for future
227+
* authentication) secrets with malicious 3rd parties. Defaults to "same-origin".
228+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#sending_a_request_with_credentials_included
229+
*
230+
* @param {HTMLElement} trigger_btn Button that triggers the modal to open/close
231+
* @param {Object} settings Configuration/Settings for this given modal
232+
* @return {HTMLElement} The button with an event listener
233+
*/
234+
const modalForm = function (trigger_btn, settings) {
191235
// Default settings
192236
let defaults = {
193237
modalID: "#modal",
@@ -196,6 +240,7 @@ const modalForm = function(elem, options) {
196240
formURL: null,
197241
isDeleteForm: false,
198242
errorClass: "is-invalid",
243+
credentials: 'same-origin', // Choices: omit, include, same-origin
199244
asyncUpdate: false,
200245
asyncSettings: {
201246
closeOnSubmit: false,
@@ -207,11 +252,11 @@ const modalForm = function(elem, options) {
207252
}
208253
};
209254

210-
let settings = {...defaults, ...options}
255+
const replenished_settings = {...defaults, ...settings}
211256

212-
elem.addEventListener('click', () => {
213-
modalFormCallback(settings);
257+
trigger_btn.addEventListener('click', () => {
258+
modalFormCallback(replenished_settings);
214259
})
215260

216-
return elem;
261+
return trigger_btn;
217262
}

0 commit comments

Comments
 (0)