1+ 'use strict' ;
12/*
23django-bootstrap-modal-forms
34version : 2.2.1
45Copyright (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+ */
813const 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+ */
3450const 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+ */
5274const 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+ */
85116const 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+ */
158195const 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