Commit 6dec66d1 authored by Andreas Fernandez's avatar Andreas Fernandez
Browse files

[TASK] Make AJAX request abortion easier

The AJAX API doesn't expose the AbortController anymore as it has no
benefit for a developer, besides aborting a request. For this reason, the
AJAX API removes the `getAbort()` method and replaces it with an
`abort()` method, which utilizes the controller directly.

Resolves: #90292
Releases: master
Change-Id: Id6355663bc00bbb763692ca3b7fab145cb8cc55e
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63141

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent 4fa752ee
......@@ -621,7 +621,7 @@ class InlineControlContainer {
progress.start();
} else {
// Abort loading if collapsed again
this.requestQueue[objectId].getAbort().abort();
this.requestQueue[objectId].abort();
delete this.requestQueue[objectId];
delete this.progessQueue[objectId];
progress.done();
......
......@@ -161,7 +161,7 @@ class SlugElement {
input.manual = this.$inputField.val();
}
if (this.request instanceof AjaxRequest) {
this.request.getAbort().abort();
this.request.abort();
}
this.request = (new AjaxRequest(TYPO3.settings.ajaxUrls.record_slug_suggest));
this.request.post({
......
......@@ -119,12 +119,10 @@ class AjaxRequest {
}
/**
* Gets an instance of AbortController used to abort the current request
*
* @return {AbortController}
* Aborts the current request by using the AbortController
*/
public getAbort(): AbortController {
return this.abortController;
public abort(): void {
this.abortController.abort();
}
/**
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest"],(function(e,t,i,l){"use strict";var s,n;!function(e){e.toggleButton=".t3js-form-field-slug-toggle",e.recreateButton=".t3js-form-field-slug-recreate",e.inputField=".t3js-form-field-slug-input",e.readOnlyField=".t3js-form-field-slug-readonly",e.hiddenField=".t3js-form-field-slug-hidden"}(s||(s={})),function(e){e.AUTO="auto",e.RECREATE="recreate",e.MANUAL="manual"}(n||(n={}));return class{constructor(e,t){this.options=null,this.$fullElement=null,this.manuallyChanged=!1,this.$readOnlyField=null,this.$inputField=null,this.$hiddenField=null,this.request=null,this.fieldsToListenOn={},this.options=t,this.fieldsToListenOn=this.options.listenerFieldNames||{},i(()=>{this.$fullElement=i(e),this.$inputField=this.$fullElement.find(s.inputField),this.$readOnlyField=this.$fullElement.find(s.readOnlyField),this.$hiddenField=this.$fullElement.find(s.hiddenField),this.registerEvents()})}registerEvents(){const e=Object.keys(this.getAvailableFieldsForProposalGeneration()).map(e=>this.fieldsToListenOn[e]);e.length>0?("new"===this.options.command&&i(this.$fullElement).on("keyup",e.join(","),()=>{this.manuallyChanged||this.sendSlugProposal(n.AUTO)}),i(this.$fullElement).on("click",s.recreateButton,e=>{e.preventDefault(),this.$readOnlyField.hasClass("hidden")&&(this.$readOnlyField.toggleClass("hidden",!1),this.$inputField.toggleClass("hidden",!0)),this.sendSlugProposal(n.RECREATE)})):i(this.$fullElement).find(s.recreateButton).addClass("disabled").prop("disabled",!0),i(this.$inputField).on("keyup",()=>{this.manuallyChanged=!0,this.sendSlugProposal(n.MANUAL)}),i(this.$fullElement).on("click",s.toggleButton,e=>{e.preventDefault();const t=this.$readOnlyField.hasClass("hidden");this.$readOnlyField.toggleClass("hidden",!t),this.$inputField.toggleClass("hidden",t),t?(this.$inputField.val()!==this.$readOnlyField.val()?this.$readOnlyField.val(this.$inputField.val()):(this.manuallyChanged=!1,this.$fullElement.find(".t3js-form-proposal-accepted").addClass("hidden"),this.$fullElement.find(".t3js-form-proposal-different").addClass("hidden")),this.$hiddenField.val(this.$readOnlyField.val())):this.$hiddenField.val(this.$inputField.val())})}sendSlugProposal(e){const t={};e===n.AUTO||e===n.RECREATE?(i.each(this.getAvailableFieldsForProposalGeneration(),(e,l)=>{t[e]=i('[data-formengine-input-name="'+l+'"]').val()}),!0===this.options.includeUidInValues&&(t.uid=this.options.recordId.toString())):t.manual=this.$inputField.val(),this.request instanceof l&&this.request.getAbort().abort(),this.request=new l(TYPO3.settings.ajaxUrls.record_slug_suggest),this.request.post({values:t,mode:e,tableName:this.options.tableName,pageId:this.options.pageId,parentPageId:this.options.parentPageId,recordId:this.options.recordId,language:this.options.language,fieldName:this.options.fieldName,command:this.options.command,signature:this.options.signature}).then(async t=>{const i=await t.resolve();i.hasConflicts?(this.$fullElement.find(".t3js-form-proposal-accepted").addClass("hidden"),this.$fullElement.find(".t3js-form-proposal-different").removeClass("hidden").find("span").text(i.proposal)):(this.$fullElement.find(".t3js-form-proposal-accepted").removeClass("hidden").find("span").text(i.proposal),this.$fullElement.find(".t3js-form-proposal-different").addClass("hidden")),this.$hiddenField.val()!==i.proposal&&this.$fullElement.find("input").trigger("change"),e===n.AUTO||e===n.RECREATE?(this.$readOnlyField.val(i.proposal),this.$hiddenField.val(i.proposal),this.$inputField.val(i.proposal)):this.$hiddenField.val(i.proposal)}).finally(()=>{this.request=null})}getAvailableFieldsForProposalGeneration(){const e={};return i.each(this.fieldsToListenOn,(t,l)=>{i('[data-formengine-input-name="'+l+'"]').length>0&&(e[t]=l)}),e}}}));
\ No newline at end of file
define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest"],(function(e,i,t,l){"use strict";var s,n;!function(e){e.toggleButton=".t3js-form-field-slug-toggle",e.recreateButton=".t3js-form-field-slug-recreate",e.inputField=".t3js-form-field-slug-input",e.readOnlyField=".t3js-form-field-slug-readonly",e.hiddenField=".t3js-form-field-slug-hidden"}(s||(s={})),function(e){e.AUTO="auto",e.RECREATE="recreate",e.MANUAL="manual"}(n||(n={}));return class{constructor(e,i){this.options=null,this.$fullElement=null,this.manuallyChanged=!1,this.$readOnlyField=null,this.$inputField=null,this.$hiddenField=null,this.request=null,this.fieldsToListenOn={},this.options=i,this.fieldsToListenOn=this.options.listenerFieldNames||{},t(()=>{this.$fullElement=t(e),this.$inputField=this.$fullElement.find(s.inputField),this.$readOnlyField=this.$fullElement.find(s.readOnlyField),this.$hiddenField=this.$fullElement.find(s.hiddenField),this.registerEvents()})}registerEvents(){const e=Object.keys(this.getAvailableFieldsForProposalGeneration()).map(e=>this.fieldsToListenOn[e]);e.length>0?("new"===this.options.command&&t(this.$fullElement).on("keyup",e.join(","),()=>{this.manuallyChanged||this.sendSlugProposal(n.AUTO)}),t(this.$fullElement).on("click",s.recreateButton,e=>{e.preventDefault(),this.$readOnlyField.hasClass("hidden")&&(this.$readOnlyField.toggleClass("hidden",!1),this.$inputField.toggleClass("hidden",!0)),this.sendSlugProposal(n.RECREATE)})):t(this.$fullElement).find(s.recreateButton).addClass("disabled").prop("disabled",!0),t(this.$inputField).on("keyup",()=>{this.manuallyChanged=!0,this.sendSlugProposal(n.MANUAL)}),t(this.$fullElement).on("click",s.toggleButton,e=>{e.preventDefault();const i=this.$readOnlyField.hasClass("hidden");this.$readOnlyField.toggleClass("hidden",!i),this.$inputField.toggleClass("hidden",i),i?(this.$inputField.val()!==this.$readOnlyField.val()?this.$readOnlyField.val(this.$inputField.val()):(this.manuallyChanged=!1,this.$fullElement.find(".t3js-form-proposal-accepted").addClass("hidden"),this.$fullElement.find(".t3js-form-proposal-different").addClass("hidden")),this.$hiddenField.val(this.$readOnlyField.val())):this.$hiddenField.val(this.$inputField.val())})}sendSlugProposal(e){const i={};e===n.AUTO||e===n.RECREATE?(t.each(this.getAvailableFieldsForProposalGeneration(),(e,l)=>{i[e]=t('[data-formengine-input-name="'+l+'"]').val()}),!0===this.options.includeUidInValues&&(i.uid=this.options.recordId.toString())):i.manual=this.$inputField.val(),this.request instanceof l&&this.request.abort(),this.request=new l(TYPO3.settings.ajaxUrls.record_slug_suggest),this.request.post({values:i,mode:e,tableName:this.options.tableName,pageId:this.options.pageId,parentPageId:this.options.parentPageId,recordId:this.options.recordId,language:this.options.language,fieldName:this.options.fieldName,command:this.options.command,signature:this.options.signature}).then(async i=>{const t=await i.resolve();t.hasConflicts?(this.$fullElement.find(".t3js-form-proposal-accepted").addClass("hidden"),this.$fullElement.find(".t3js-form-proposal-different").removeClass("hidden").find("span").text(t.proposal)):(this.$fullElement.find(".t3js-form-proposal-accepted").removeClass("hidden").find("span").text(t.proposal),this.$fullElement.find(".t3js-form-proposal-different").addClass("hidden")),this.$hiddenField.val()!==t.proposal&&this.$fullElement.find("input").trigger("change"),e===n.AUTO||e===n.RECREATE?(this.$readOnlyField.val(t.proposal),this.$hiddenField.val(t.proposal),this.$inputField.val(t.proposal)):this.$hiddenField.val(t.proposal)}).finally(()=>{this.request=null})}getAvailableFieldsForProposalGeneration(){const e={};return t.each(this.fieldsToListenOn,(i,l)=>{t('[data-formengine-input-name="'+l+'"]').length>0&&(e[i]=l)}),e}}}));
\ No newline at end of file
......@@ -152,10 +152,10 @@ Example:
});
getAbort()
abort()
~~~~~~~~~~
Returns an instance of `AbortController`_ that can be used to abort the request.
Aborts the request by using its instance of `AbortController`_.
Response
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports","../BackwardCompat/JQueryNativePromises","./AjaxResponse","./ResponseError","./InputTransformer"],(function(t,e,s,n,r,o){"use strict";class a{constructor(t){this.queryArguments="",this.url=t,this.abortController=new AbortController,s.default.support()}withQueryArguments(t){const e=this.clone();return e.queryArguments=(""!==e.queryArguments?"&":"")+o.InputTransformer.toSearchParams(t),e}async get(t={}){const e=await this.send(Object.assign(Object.assign({},{method:"GET"}),t));return new n.AjaxResponse(e)}async post(t,e={}){const s={body:"string"==typeof t?t:o.InputTransformer.toFormData(t),cache:"no-cache",method:"POST"},r=await this.send(Object.assign(Object.assign({},s),e));return new n.AjaxResponse(r)}async put(t,e={}){const s={body:"string"==typeof t?t:o.InputTransformer.toFormData(t),cache:"no-cache",method:"PUT"},r=await this.send(Object.assign(Object.assign({},s),e));return new n.AjaxResponse(r)}async delete(t={},e={}){const s={cache:"no-cache",method:"DELETE"};"object"==typeof t&&Object.keys(t).length>0?s.body=o.InputTransformer.toFormData(t):"string"==typeof t&&(s.body=t);const r=await this.send(Object.assign(Object.assign({},s),e));return new n.AjaxResponse(r)}getAbort(){return this.abortController}clone(){return Object.assign(Object.create(this),this)}async send(t={}){const e=await fetch(this.composeRequestUrl(),this.getMergedOptions(t));if(!e.ok)throw new r.ResponseError(e);return e}composeRequestUrl(){let t=this.url;if("?"===t.charAt(0)&&(t=window.location.origin+window.location.pathname+t),t=new URL(t,window.location.origin).toString(),""!==this.queryArguments){t+=(this.url.includes("?")?"&":"?")+this.queryArguments}return t}getMergedOptions(t){return Object.assign(Object.assign(Object.assign({},a.defaultOptions),t),{signal:this.abortController.signal})}}return a.defaultOptions={credentials:"same-origin"},a}));
\ No newline at end of file
define(["require","exports","../BackwardCompat/JQueryNativePromises","./AjaxResponse","./ResponseError","./InputTransformer"],(function(t,e,s,n,r,o){"use strict";class a{constructor(t){this.queryArguments="",this.url=t,this.abortController=new AbortController,s.default.support()}withQueryArguments(t){const e=this.clone();return e.queryArguments=(""!==e.queryArguments?"&":"")+o.InputTransformer.toSearchParams(t),e}async get(t={}){const e=await this.send(Object.assign(Object.assign({},{method:"GET"}),t));return new n.AjaxResponse(e)}async post(t,e={}){const s={body:"string"==typeof t?t:o.InputTransformer.toFormData(t),cache:"no-cache",method:"POST"},r=await this.send(Object.assign(Object.assign({},s),e));return new n.AjaxResponse(r)}async put(t,e={}){const s={body:"string"==typeof t?t:o.InputTransformer.toFormData(t),cache:"no-cache",method:"PUT"},r=await this.send(Object.assign(Object.assign({},s),e));return new n.AjaxResponse(r)}async delete(t={},e={}){const s={cache:"no-cache",method:"DELETE"};"object"==typeof t&&Object.keys(t).length>0?s.body=o.InputTransformer.toFormData(t):"string"==typeof t&&(s.body=t);const r=await this.send(Object.assign(Object.assign({},s),e));return new n.AjaxResponse(r)}abort(){this.abortController.abort()}clone(){return Object.assign(Object.create(this),this)}async send(t={}){const e=await fetch(this.composeRequestUrl(),this.getMergedOptions(t));if(!e.ok)throw new r.ResponseError(e);return e}composeRequestUrl(){let t=this.url;if("?"===t.charAt(0)&&(t=window.location.origin+window.location.pathname+t),t=new URL(t,window.location.origin).toString(),""!==this.queryArguments){t+=(this.url.includes("?")?"&":"?")+this.queryArguments}return t}getMergedOptions(t){return Object.assign(Object.assign(Object.assign({},a.defaultOptions),t),{signal:this.abortController.signal})}}return a.defaultOptions={credentials:"same-origin"},a}));
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment