177 lines
4.3 KiB
JavaScript
177 lines
4.3 KiB
JavaScript
import Rails from '@rails/ujs';
|
|
import debounce from 'debounce';
|
|
|
|
export { debounce };
|
|
export const { fire, csrfToken } = Rails;
|
|
|
|
export function show(el) {
|
|
el && el.classList.remove('hidden');
|
|
}
|
|
|
|
export function hide(el) {
|
|
el && el.classList.add('hidden');
|
|
}
|
|
|
|
export function toggle(el, force) {
|
|
if (force == undefined) {
|
|
el & el.classList.toggle('hidden');
|
|
} else if (force) {
|
|
el && el.classList.remove('hidden');
|
|
} else {
|
|
el && el.classList.add('hidden');
|
|
}
|
|
}
|
|
|
|
export function enable(el) {
|
|
el && (el.disabled = false);
|
|
}
|
|
|
|
export function disable(el) {
|
|
el && (el.disabled = true);
|
|
}
|
|
|
|
export function hasClass(el, cssClass) {
|
|
return el && el.classList.contains(cssClass);
|
|
}
|
|
|
|
export function addClass(el, cssClass) {
|
|
el && el.classList.add(cssClass);
|
|
}
|
|
|
|
export function removeClass(el, cssClass) {
|
|
el && el.classList.remove(cssClass);
|
|
}
|
|
|
|
export function delegate(eventNames, selector, callback) {
|
|
eventNames
|
|
.split(' ')
|
|
.forEach((eventName) =>
|
|
Rails.delegate(document, selector, eventName, callback)
|
|
);
|
|
}
|
|
|
|
// A promise-based wrapper for Rails.ajax().
|
|
//
|
|
// Returns a Promise that is either:
|
|
// - resolved in case of a 20* HTTP response code,
|
|
// - rejected with an Error object otherwise.
|
|
//
|
|
// See Rails.ajax() code for more details.
|
|
export function ajax(options) {
|
|
return new Promise((resolve, reject) => {
|
|
Object.assign(options, {
|
|
success: (response, statusText, xhr) => {
|
|
resolve({ response, statusText, xhr });
|
|
},
|
|
error: (response, statusText, xhr) => {
|
|
// NB: on HTTP/2 connections, statusText is always empty.
|
|
let error = new Error(
|
|
`Erreur ${xhr.status}` + (statusText ? ` : ${statusText}` : '')
|
|
);
|
|
Object.assign(error, { response, statusText, xhr });
|
|
reject(error);
|
|
}
|
|
});
|
|
Rails.ajax(options);
|
|
});
|
|
}
|
|
|
|
export function getJSON(url, data, method = 'GET') {
|
|
const { query, ...options } = fetchOptions(data, method);
|
|
|
|
return fetch(`${url}${query}`, options).then((response) => {
|
|
if (response.ok) {
|
|
if (response.status === 204) {
|
|
return null;
|
|
}
|
|
return response.json();
|
|
}
|
|
const error = new Error(response.statusText || response.status);
|
|
error.response = response;
|
|
throw error;
|
|
});
|
|
}
|
|
|
|
export function scrollTo(container, scrollTo) {
|
|
container.scrollTop =
|
|
offset(scrollTo).top - offset(container).top + container.scrollTop;
|
|
}
|
|
|
|
export function scrollToBottom(container) {
|
|
container.scrollTop = container.scrollHeight;
|
|
}
|
|
|
|
export function on(selector, eventName, fn) {
|
|
[...document.querySelectorAll(selector)].forEach((element) =>
|
|
element.addEventListener(eventName, (event) => fn(event, event.detail))
|
|
);
|
|
}
|
|
|
|
export function isNumeric(n) {
|
|
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
}
|
|
|
|
function offset(element) {
|
|
const rect = element.getBoundingClientRect();
|
|
return {
|
|
top: rect.top + document.body.scrollTop,
|
|
left: rect.left + document.body.scrollLeft
|
|
};
|
|
}
|
|
|
|
// Takes a promise, and return a promise that times out after the given delay.
|
|
export function timeoutable(promise, timeoutDelay) {
|
|
let timeoutPromise = new Promise((resolve, reject) => {
|
|
setTimeout(() => {
|
|
reject(new Error(`Promise timed out after ${timeoutDelay}ms`));
|
|
}, timeoutDelay);
|
|
});
|
|
return Promise.race([promise, timeoutPromise]);
|
|
}
|
|
|
|
const FETCH_TIMEOUT = 30 * 1000; // 30 sec
|
|
|
|
function fetchOptions(data, method = 'GET') {
|
|
const options = {
|
|
query: '',
|
|
method: method.toUpperCase(),
|
|
headers: {
|
|
accept: 'application/json',
|
|
'x-csrf-token': csrfToken(),
|
|
'x-requested-with': 'XMLHttpRequest'
|
|
},
|
|
credentials: 'same-origin'
|
|
};
|
|
|
|
if (data) {
|
|
if (options.method === 'GET') {
|
|
options.query = objectToQuerystring(data);
|
|
} else {
|
|
options.headers['content-type'] = 'application/json';
|
|
options.body = JSON.stringify(data);
|
|
}
|
|
}
|
|
|
|
if (window.AbortController) {
|
|
const controller = new AbortController();
|
|
options.signal = controller.signal;
|
|
|
|
setTimeout(() => {
|
|
controller.abort();
|
|
}, FETCH_TIMEOUT);
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
function objectToQuerystring(obj) {
|
|
return Object.keys(obj).reduce(function (query, key, i) {
|
|
return [
|
|
query,
|
|
i === 0 ? '?' : '&',
|
|
encodeURIComponent(key),
|
|
'=',
|
|
encodeURIComponent(obj[key])
|
|
].join('');
|
|
}, '');
|
|
}
|