@@ -229,29 +229,53 @@ export default Base.extend({
229229 $form . trigger ( "submit" ) ;
230230
231231 self . loading . show ( false ) ;
232- $form . ajaxSubmit ( {
233- timeout : options . timeout ,
234- data : extraData ,
235- url : url ,
236- error : function ( xhr , textStatus , errorStatus ) {
237- self . loading . hide ( ) ;
238- if ( textStatus === "timeout" && options . onTimeout ) {
239- options . onTimeout . apply ( self , xhr , errorStatus ) ;
240- // on "error", "abort", and "parsererror"
241- } else if ( options . onError ) {
242- if ( typeof options . onError === "string" ) {
243- window [ options . onError ] ( xhr , textStatus , errorStatus ) ;
244- } else {
245- options . onError ( xhr , textStatus , errorStatus ) ;
246- }
247- } else {
248- // window.alert(_t('There was an error submitting the form.'));
249- console . log ( "error happened" , textStatus , " do something" ) ;
250- }
251- self . emit ( "formActionError" , [ xhr , textStatus , errorStatus ] ) ;
252- } ,
253- success : function ( response , state , xhr , form ) {
232+
233+ // Use native fetch API with FormData
234+ const formData = new FormData ( $form [ 0 ] ) ;
235+
236+ // Add extra data from the clicked action
237+ for ( const key in extraData ) {
238+ if ( extraData [ key ] ) {
239+ formData . append ( key , extraData [ key ] ) ;
240+ }
241+ }
242+
243+ // Setup timeout using AbortController
244+ const controller = new AbortController ( ) ;
245+ const timeoutId = setTimeout ( ( ) => controller . abort ( ) , options . timeout ) ;
246+
247+ fetch ( url , {
248+ method : $form . attr ( "method" ) || "POST" ,
249+ body : formData ,
250+ signal : controller . signal ,
251+ credentials : "same-origin" ,
252+ } )
253+ . then ( ( response ) => {
254+ clearTimeout ( timeoutId ) ;
255+
256+ // Create a mock xhr object for compatibility with existing callbacks
257+ const mockXhr = {
258+ status : response . status ,
259+ statusText : response . statusText ,
260+ getResponseHeader : ( header ) => response . headers . get ( header ) ,
261+ getAllResponseHeaders : ( ) => {
262+ let headers = "" ;
263+ response . headers . forEach ( ( value , key ) => {
264+ headers += `${ key } : ${ value } \r\n` ;
265+ } ) ;
266+ return headers ;
267+ } ,
268+ } ;
269+
270+ return response . text ( ) . then ( ( text ) => ( {
271+ response : text ,
272+ state : "success" ,
273+ xhr : mockXhr ,
274+ } ) ) ;
275+ } )
276+ . then ( ( { response, state, xhr } ) => {
254277 self . loading . hide ( ) ;
278+
255279 // if error is found (NOTE: check for both the portal errors
256280 // and the form field-level errors)
257281 if (
@@ -265,10 +289,10 @@ export default Base.extend({
265289 response ,
266290 state ,
267291 xhr ,
268- form
292+ $ form[ 0 ]
269293 ) ;
270294 } else {
271- options . onFormError ( self , response , state , xhr , form ) ;
295+ options . onFormError ( self , response , state , xhr , $ form[ 0 ] ) ;
272296 }
273297 } else {
274298 self . redraw ( response , patternOptions ) ;
@@ -290,9 +314,9 @@ export default Base.extend({
290314
291315 if ( options . onSuccess ) {
292316 if ( typeof options . onSuccess === "string" ) {
293- window [ options . onSuccess ] ( self , response , state , xhr , form ) ;
317+ window [ options . onSuccess ] ( self , response , state , xhr , $ form[ 0 ] ) ;
294318 } else {
295- options . onSuccess ( self , response , state , xhr , form ) ;
319+ options . onSuccess ( self , response , state , xhr , $ form[ 0 ] ) ;
296320 }
297321 }
298322
@@ -305,9 +329,37 @@ export default Base.extend({
305329 self . reloadWindow ( ) ;
306330 }
307331 }
308- self . emit ( "formActionSuccess" , [ response , state , xhr , form ] ) ;
309- } ,
310- } ) ;
332+ self . emit ( "formActionSuccess" , [ response , state , xhr , $form [ 0 ] ] ) ;
333+ } )
334+ . catch ( ( error ) => {
335+ clearTimeout ( timeoutId ) ;
336+ self . loading . hide ( ) ;
337+
338+ const textStatus = error . name === "AbortError" ? "timeout" : "error" ;
339+ const errorStatus = error . message ;
340+
341+ // Create a mock xhr object for error callbacks
342+ const mockXhr = {
343+ status : 0 ,
344+ statusText : textStatus ,
345+ responseText : "" ,
346+ } ;
347+
348+ if ( textStatus === "timeout" && options . onTimeout ) {
349+ options . onTimeout . apply ( self , [ mockXhr , errorStatus ] ) ;
350+ // on "error", "abort", and "parsererror"
351+ } else if ( options . onError ) {
352+ if ( typeof options . onError === "string" ) {
353+ window [ options . onError ] ( mockXhr , textStatus , errorStatus ) ;
354+ } else {
355+ options . onError ( mockXhr , textStatus , errorStatus ) ;
356+ }
357+ } else {
358+ // window.alert(_t('There was an error submitting the form.'));
359+ console . log ( "error happened" , textStatus , " do something" ) ;
360+ }
361+ self . emit ( "formActionError" , [ mockXhr , textStatus , errorStatus ] ) ;
362+ } ) ;
311363 } ,
312364 handleLinkAction : function ( $action , options , patternOptions ) {
313365 var self = this ;
0 commit comments