Allow detached AJAX request to be called with 2 params

This allows Snowboard.request() to be called with two params, assuming that no element is attached to the request.
This commit is contained in:
Ben Thomson 2022-10-07 11:13:38 +08:00
parent 08785a4a68
commit 9be71ce1a6
2 changed files with 79 additions and 8 deletions

View File

@ -14,22 +14,43 @@ class Request extends Snowboard.PluginBase {
/**
* Constructor.
*
* The constructor accepts 2 or 3 parameters.
*
* If 2 parameters are provided, the first parameter is the handler name and the second
* parameter is the options. This assumes that this is a detached AJAX request not connected to
* an element.
*
* If 3 parameters are provided, the first parameter is an element or a selector, and the second
* and third parameters are the handler and options, respectively.
*
* @param {HTMLElement|string} element
* @param {string} handler
* @param {string|Object} handler
* @param {Object} options
*/
construct(element, handler, options) {
if (typeof element === 'string') {
const matchedElement = document.querySelector(element);
if (matchedElement === null) {
throw new Error(`No element was found with the given selector: ${element}`);
// Allow the element to be a handler name.
// This assumes the request is being made against no element, and the handler parameter
// will contain options.
if (this.isHandlerName(element)) {
this.element = null;
this.handler = element;
this.options = handler || {};
} else {
const matchedElement = document.querySelector(element);
if (matchedElement === null) {
throw new Error(`No element was found with the given selector: ${element}`);
}
this.element = matchedElement;
this.handler = handler;
this.options = options || {};
}
this.element = matchedElement;
} else {
this.element = element;
this.handler = handler;
this.options = options || {};
}
this.handler = handler;
this.options = options || {};
this.fetchOptions = {};
this.responseData = null;
this.responseError = null;
@ -132,7 +153,7 @@ class Request extends Snowboard.PluginBase {
throw new Error('The AJAX handler name is not specified.');
}
if (!this.handler.match(/^(?:\w+:{2})?on*/)) {
if (!this.isHandlerName(this.handler)) {
throw new Error('Invalid AJAX handler name. The correct handler name format is: "onEvent".');
}
}
@ -811,6 +832,16 @@ class Request extends Snowboard.PluginBase {
error.trace = trace || [];
return error;
}
/**
* Checks a given string to see if it is a valid AJAX handler name.
*
* @param {String} name
* @returns {Boolean}
*/
isHandlerName(name) {
return /^(?:\w+:{2})?on[A-Z0-9]/.test(name);
}
}
Snowboard.addPlugin('request', Request);

View File

@ -622,4 +622,44 @@ describe('Request AJAX library', function () {
}
);
});
it('can be run detached from an element with two parameters (handler and options)', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
dom.window.Snowboard.request('onTest', {
complete: (data, instance) => {
done();
return false;
}
});
}
);
});
});