Skip to content

Instantly share code, notes, and snippets.

@jiyuujin
Last active March 24, 2020 06:02
Show Gist options
  • Save jiyuujin/3576ba4159e81c2d7f1c5ad263e78b29 to your computer and use it in GitHub Desktop.
Save jiyuujin/3576ba4159e81c2d7f1c5ad263e78b29 to your computer and use it in GitHub Desktop.
[doubleSubmit対策] Enterによる連打、ダブルクリックによるリクエストを禁止する
import { FormControl } from './FormControl';
import { LinkControl } from './LinkControl';
[...document.getElementsByClassName('js-double_submit')].forEach((form) => {
if (form.dataset.type === 'default') {
const formControl = new FormControl(form);
formControl.initNoStrict();
} else {
const formControl = new FormControl(form);
formControl.init();
}
});
const linkSelector = [
'.js-double_click_link:not([target="_blank"])',
'.breadcrumb-section a',
'.pagenation-init a',
'a[href*="sort:"]',
];
[...document.querySelectorAll(linkSelector.join(', '))].forEach((link) => {
const linkControl = new LinkControl(link);
linkControl.initNoStrict();
});
export class FormControl {
constructor(form) {
this.form = form;
this.hiddenInput = null;
this.shouldSubmit = true;
}
/**
*緩めの2重クリック対策
*/
initNoStrict() {
this.attachNoStrictSubmitEvent();
}
attachNoStrictSubmitEvent() {
this.form.addEventListener('submit', (e) => {
if (e.currentTarget.dataset.submitted) {
e.preventDefault();
e.stopPropagation();
if (process.env.NODE_ENV !== 'production') {
console.log('緩めの2重クリック対策が有効です');
}
return;
}
e.currentTarget.dataset.submitted = 'true';
});
}
/**
* 強固な2重クリック対策
*/
init() {
this.attachClickSubmitEvent();
this.attachSubmitEvent();
}
querySubmitInput() {
return [...this.form.querySelectorAll('[type="submit"]')];
}
saveSubmitInput(submitInput) {
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = submitInput.name;
hiddenInput.value = submitInput.value;
this.hiddenInput = hiddenInput;
}
generateSubmitInput() {
this.form.appendChild(this.hiddenInput);
}
attachClickSubmitEvent() {
this.querySubmitInput().forEach((input) => {
input.addEventListener('click', (e) => {
this.clickSubmitHandler(e);
});
});
}
clickSubmitHandler(e) {
const inputSubmit = e.currentTarget;
this.saveSubmitInput(inputSubmit);
}
attachSubmitEvent() {
this.form.addEventListener('submit', (e) => {
this.submitHandler(e);
});
}
submitHandler(e) {
e.preventDefault();
e.stopPropagation();
if (this.shouldSubmit) {
const submitInputs = this.querySubmitInput();
if (this.hiddenInput === null && submitInputs.length !== 0) {
this.saveSubmitInput(submitInputs[0]);
}
this.generateSubmitInput();
this.form.submit();
} else if (process.env.NODE_ENV !== 'production') {
console.log('強固な2重クリック対策が有効です');
}
this.shouldSubmit = false;
}
}
export class LinkControl {
constructor(link) {
this.link = link;
}
/**
*緩めの2重クリック対策
*/
initNoStrict() {
this.attachSubmitEvent();
}
notDoubleClick() {
this.link.prop('disabled', false);
this.link.on('click', () => {
setTimeout(() => {
this.link.prop('disabled', true);
}, 0);
});
}
attachSubmitEvent() {
this.link.addEventListener('click', (e) => {
if (e.currentTarget.dataset.clicked) {
e.preventDefault();
e.stopPropagation();
if (process.env.NODE_ENV !== 'production') {
console.log('2重クリック対策が有効です');
}
return;
}
e.currentTarget.dataset.clicked = 'true';
});
this.link.addEventListener('beforeunload', (e) => {});
this.link.addEventListener('unload', (e) => {});
if (typeof window.onpageshow !== 'undefined') {
this.link.onpageshow = function() {
this.notDoubleClick();
};
} else {
this.link.onload = function() {
this.notDoubleClick();
};
window.onunload = function() {};
}
this.link.addEventListener('pagehide', (e) => {
if (e.currentTarget.dataset.clicked) {
setTimeout(() => {
e.currentTarget.dataset.clicked = 'false';
}, 0);
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment