115 lines
4.6 KiB
JavaScript
115 lines
4.6 KiB
JavaScript
(function (window, document) {
|
|
'use strict';
|
|
|
|
var nativeFetch = window.fetch.bind(window);
|
|
|
|
function toast(text) {
|
|
var old = document.querySelector('.ajax-error-toast');
|
|
if (old) old.remove();
|
|
var element = document.createElement('div');
|
|
element.className = 'ajax-error-toast';
|
|
element.setAttribute('role', 'alert');
|
|
element.textContent = text;
|
|
document.body.appendChild(element);
|
|
window.setTimeout(function () { element.remove(); }, 7000);
|
|
}
|
|
|
|
function addCsrf(formData) {
|
|
var token = window.APP_CSRF;
|
|
if (token && token.name && !formData.has(token.name)) {
|
|
formData.append(token.name, token.value);
|
|
}
|
|
return formData;
|
|
}
|
|
|
|
function secureFetch(url, options) {
|
|
options = Object.assign({}, options || {});
|
|
var method = String(options.method || 'GET').toUpperCase();
|
|
var token = window.APP_CSRF;
|
|
var target;
|
|
try {
|
|
target = new URL(url, window.location.href);
|
|
} catch (_error) {
|
|
target = null;
|
|
}
|
|
if (target && target.origin === window.location.origin && !/^(GET|HEAD|OPTIONS)$/.test(method) && token && token.name) {
|
|
if (options.body instanceof FormData) {
|
|
addCsrf(options.body);
|
|
} else if (options.body instanceof URLSearchParams) {
|
|
options.body = new URLSearchParams(options.body);
|
|
if (!options.body.has(token.name)) options.body.append(token.name, token.value);
|
|
}
|
|
}
|
|
return nativeFetch(url, options);
|
|
}
|
|
|
|
window.fetch = secureFetch;
|
|
|
|
async function request(url, options) {
|
|
options = options || {};
|
|
options.headers = Object.assign({
|
|
Accept: 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}, options.headers || {});
|
|
if (options.body instanceof FormData) addCsrf(options.body);
|
|
|
|
var response;
|
|
try {
|
|
response = await window.fetch(url, options);
|
|
} catch (error) {
|
|
throw new Error('Tidak dapat terhubung ke server. Periksa jaringan atau Apache.');
|
|
}
|
|
|
|
var contentType = response.headers.get('content-type') || '';
|
|
if (contentType.indexOf('application/json') === -1) {
|
|
var raw = await response.text();
|
|
if (response.redirected || /<(?:html|!doctype)/i.test(raw)) {
|
|
throw new Error('Sesi berakhir atau server mengirim halaman error. Silakan login ulang.');
|
|
}
|
|
throw new Error(raw.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 240) || 'Respons server tidak valid.');
|
|
}
|
|
|
|
var payload = await response.json();
|
|
if (!response.ok) throw new Error(payload.message || ('Permintaan gagal (HTTP ' + response.status + ').'));
|
|
return payload;
|
|
}
|
|
|
|
window.App = Object.assign(window.App || {}, {
|
|
request: request,
|
|
addCsrf: addCsrf,
|
|
showError: toast
|
|
});
|
|
|
|
if (window.jQuery) {
|
|
window.jQuery.ajaxSetup({headers: {'X-Requested-With': 'XMLHttpRequest'}});
|
|
window.jQuery.ajaxPrefilter(function (options, originalOptions) {
|
|
var method = String(options.type || options.method || 'GET').toUpperCase();
|
|
var token = window.APP_CSRF;
|
|
if (/^(GET|HEAD|OPTIONS)$/.test(method) || !token || !token.name) return;
|
|
|
|
if (options.data instanceof FormData) {
|
|
if (!options.data.has(token.name)) options.data.append(token.name, token.value);
|
|
return;
|
|
}
|
|
|
|
if (typeof options.data === 'string') {
|
|
var encodedName = encodeURIComponent(token.name);
|
|
if (options.data.indexOf(encodedName + '=') === -1) {
|
|
options.data += (options.data ? '&' : '') + encodedName + '=' + encodeURIComponent(token.value);
|
|
}
|
|
return;
|
|
}
|
|
|
|
options.data = window.jQuery.extend({}, originalOptions.data || options.data || {});
|
|
if (typeof options.data[token.name] === 'undefined') options.data[token.name] = token.value;
|
|
});
|
|
window.jQuery(document).ajaxError(function (_event, xhr, _settings, error) {
|
|
var message = 'Pemanggilan data gagal';
|
|
if (xhr.status === 401 || xhr.status === 403) message = 'Sesi atau hak akses tidak valid. Silakan login ulang.';
|
|
else if (xhr.status) message += ' (HTTP ' + xhr.status + ').';
|
|
else message += '. Periksa koneksi atau Apache.';
|
|
toast(error && error !== 'error' ? error : message);
|
|
});
|
|
}
|
|
}(window, document));
|