Make ImageChooser a subclass of Chooser

Need to split out a Chooser.initHTMLElements method so that we can set up this.previewImage before using it in getStateFromHTML.
pull/8898/head
Matt Westcott 2022-06-29 16:26:10 +01:00 zatwierdzone przez LB (Ben Johnston)
rodzic 20d941cfbf
commit 89d89334ca
2 zmienionych plików z 36 dodań i 105 usunięć

Wyświetl plik

@ -2,16 +2,12 @@ import { chooserModalOnloadHandlers } from '../../includes/chooserModal';
export class Chooser {
modalOnloadHandlers = chooserModalOnloadHandlers;
titleStateKey = 'title'; // key used in the 'state' dictionary to hold the human-readable title
chosenResponseName = 'chosen'; // identifier for the ModalWorkflow response that indicates an item was chosen
constructor(id) {
this.chooserElement = document.getElementById(`${id}-chooser`);
this.titleElement = this.chooserElement.querySelector('.title');
this.input = document.getElementById(id);
this.editLink = this.chooserElement.querySelector('.edit-link');
this.chooserBaseUrl = this.chooserElement.dataset.chooserUrl;
this.initHTMLElements(id);
this.state = this.getStateFromHTML();
for (const btn of this.chooserElement.querySelectorAll('.action-choose')) {
@ -26,6 +22,14 @@ export class Chooser {
}
}
initHTMLElements(id) {
this.chooserElement = document.getElementById(`${id}-chooser`);
this.titleElement = this.chooserElement.querySelector('.title');
this.input = document.getElementById(id);
this.editLink = this.chooserElement.querySelector('.edit-link');
this.chooserBaseUrl = this.chooserElement.dataset.chooserUrl;
}
getStateFromHTML() {
/*
Construct initial state of the chooser from the rendered (static) HTML.
@ -36,11 +40,14 @@ export class Chooser {
passed directly to chooser.setState.
*/
if (this.input.value) {
return {
const state = {
id: this.input.value,
edit_link: this.editLink.getAttribute('href'),
[this.titleStateKey]: this.titleElement.innerText,
};
if (this.titleElement && this.titleStateKey) {
state[this.titleStateKey] = this.titleElement.innerText;
}
return state;
} else {
return null;
}
@ -74,7 +81,9 @@ export class Chooser {
renderState(newState) {
this.input.setAttribute('value', newState.id);
this.titleElement.innerText = newState[this.titleStateKey];
if (this.titleElement && this.titleStateKey) {
this.titleElement.innerText = newState[this.titleStateKey];
}
this.chooserElement.classList.remove('blank');
this.editLink.setAttribute('href', newState.edit_link);
}

Wyświetl plik

@ -1,24 +1,13 @@
class ImageChooser {
constructor(id) {
this.chooserElement = document.getElementById(`${id}-chooser`);
import { Chooser } from '../../components/ChooserWidget';
class ImageChooser extends Chooser {
// eslint-disable-next-line no-undef
modalOnloadHandlers = IMAGE_CHOOSER_MODAL_ONLOAD_HANDLERS;
chosenResponseName = 'imageChosen';
initHTMLElements(id) {
super.initHTMLElements(id);
this.previewImage = this.chooserElement.querySelector('.preview-image img');
this.input = document.getElementById(id);
this.editLink = this.chooserElement.querySelector('.edit-link');
this.chooserBaseUrl = this.chooserElement.dataset.chooserUrl;
this.state = this.getStateFromHTML();
/* hook up chooser API to the buttons */
for (const btn of this.chooserElement.querySelectorAll('.action-choose')) {
btn.addEventListener('click', () => {
this.openChooserModal();
});
}
for (const btn of this.chooserElement.querySelectorAll('.action-clear')) {
btn.addEventListener('click', () => {
this.clear();
});
}
}
getStateFromHTML() {
@ -26,92 +15,25 @@ class ImageChooser {
Construct initial state of the chooser from the rendered (static) HTML.
State is either null (= no image chosen) or a dict of id, edit_link, title
and preview (= a dict of url, width, height).
The result returned from the image chooser modal (see get_image_result_data in
wagtail.images.views.chooser) is a superset of this, and can therefore be passed directly to
chooser.setState.
*/
if (this.input.value) {
return {
id: this.input.value,
edit_link: this.editLink.getAttribute('href'),
title: this.previewImage.getAttribute('alt'),
preview: {
url: this.previewImage.getAttribute('src'),
width: this.previewImage.getAttribute('width'),
height: this.previewImage.getAttribute('height'),
},
const state = super.getStateFromHTML();
if (state) {
state.title = this.previewImage.getAttribute('alt');
state.preview = {
url: this.previewImage.getAttribute('src'),
width: this.previewImage.getAttribute('width'),
height: this.previewImage.getAttribute('height'),
};
} else {
return null;
}
}
getState() {
return this.state;
}
getValue() {
return this.state && this.state.id;
}
setState(newState) {
this.state = newState;
if (newState) {
this.renderState(newState);
} else {
this.renderEmptyState();
}
}
clear() {
this.setState(null);
}
renderEmptyState() {
this.input.setAttribute('value', '');
this.chooserElement.classList.add('blank');
return state;
}
renderState(newState) {
this.input.setAttribute('value', newState.id);
super.renderState(newState);
this.previewImage.setAttribute('src', newState.preview.url);
this.previewImage.setAttribute('width', newState.preview.width);
this.previewImage.setAttribute('alt', newState.title);
this.previewImage.setAttribute('title', newState.title);
this.chooserElement.classList.remove('blank');
this.editLink.setAttribute('href', newState.edit_link);
}
getTextLabel(opts) {
if (!this.state) return null;
const result = this.state.title;
if (opts && opts.maxLength && result.length > opts.maxLength) {
return result.substring(0, opts.maxLength - 1) + '…';
}
return result;
}
focus() {
this.chooserElement.querySelector('.action-choose').focus();
}
getModalUrl() {
return this.chooserBaseUrl;
}
openChooserModal() {
// eslint-disable-next-line no-undef
ModalWorkflow({
url: this.getModalUrl(),
// eslint-disable-next-line no-undef
onload: IMAGE_CHOOSER_MODAL_ONLOAD_HANDLERS,
responses: {
imageChosen: (result) => {
this.setState(result);
},
},
});
}
}