Files

165 lines
5.4 KiB
JavaScript

import { BBoxOverlayElement } from "./BBoxOverlayElement.js";
const ELEMENT_HTML = `
<img>
<div class="overlay"></div>
<div class="actions">
<button class="select" title="Toggle Select">
<span class="p-button-icon pi pi-check"></span>
</button>
<button class="unwanted" title="Toggle Unwanted">
<span class="p-button-icon pi pi-ban"></span>
</button>
</div>
`;
const ATTRIB_DATA_SELECT = 'data-selected';
const ATTRIB_DATA_UNWANTED = 'data-unwanted';
/**
* Element that displays an image from an ImageList.
*/
export class ImageListImageElement extends HTMLElement {
constructor() {
super();
this.index = null;
// Construct the element from HTML.
this.innerHTML = ELEMENT_HTML;
this.el = {
image: this.querySelector('img'),
selectButton: this.querySelector('.select'),
unwantedButton: this.querySelector('.unwanted'),
segmentsOverlay: null
};
// Create event handlers for this instance.
this.handlerClick = this.onClick.bind(this);
this.addEventListener('click', this.handlerClick);
this.handlerMousedown = this.onMousedown.bind(this);
this.addEventListener('mousedown', this.handlerMousedown);
this.handlerImageAttributeChanged = this.onImageAttributeChanged.bind(this);
// Bind action button click handlers.
this.handlerActionSelect = this.onActionClick.bind(this, 'select');
this.el.selectButton.addEventListener('click', this.handlerActionSelect);
this.handlerActionUnwanted = this.onActionClick.bind(this, 'unwanted');
this.el.unwantedButton.addEventListener('click', this.handlerActionUnwanted);
}
// Set the image list from which the image will be displayed.
setImageList(value, index = 0) {
this.imageList = value;
this.imageList.addEventListener('image-select', this.handlerImageAttributeChanged);
this.imageList.addEventListener('image-unwanted', this.handlerImageAttributeChanged);
this.setIndex(index);
}
// Set the index of the image in the image list to display.
setIndex(value) {
if (this.index !== value) {
this.index = value;
this.el.image.src = this.imageList.getImageUrl(value);
this.updateAttributes();
// Add a segments overlay if the iamge has segment data.
const segments = this.imageList.getImageSegments(value);
if (segments) {
if (!this.el.segmentsOverlay) {
this.el.segmentsOverlay = new BBoxOverlayElement();
this.appendChild(this.el.segmentsOverlay);
}
this.el.segmentsOverlay.setSegments(segments);
} else {
// Image data does have segments.
this.removeChild(this.el.segmentsOverlay);
this.el.segmentsOverlay = null;
}
this.dispatchEvent(new CustomEvent('image-index', {
detail: {
imageList: this.imageList,
index: this.index
}
}));
}
}
// Update the attributes that decorate the image.
updateAttributes() {
const selected = this.imageList.isSelected(this.index),
unwanted = this.imageList.isUnwanted(this.index);
this.setAttribute(ATTRIB_DATA_SELECT, selected ? 'yes' : 'no');
this.setAttribute(ATTRIB_DATA_UNWANTED, unwanted ? 'yes' : 'no');
}
// Invoked when mousedown on the image.
onMousedown(event) {
this.dispatchEvent(new CustomEvent('image-mousedown', {
detail: {
button: event.button,
imageList: this.imageList,
index: this.index
}
}));
}
// Invoked when the image is clicked.
onClick() {
this.dispatchEvent(new CustomEvent('image-click', {
detail: {
imageList: this.imageList,
index: this.index
}
}));
}
// Invoked when a action button is clicked.
onActionClick(action, event) {
event.preventDefault();
event.stopPropagation();
this.dispatchEvent(new CustomEvent(`image-action`, {
detail: {
action,
imageList: this.imageList,
index: this.index
}
}));
}
// Invoked when the selection in the image list changes.
onImageAttributeChanged(event) {
const detail = event.detail;
if (detail.index === this.index) {
this.updateAttributes();
}
}
// Return a promise that is resoved with the width and height of an image.
async getImageSize() {
const self = this;
return new Promise((resolve, reject) => {
function check(n) {
if (self.el.image.naturalWidth) {
resolve([
self.el.image.naturalWidth,
self.el.image.naturalHeight
]);
}
else if (n > 100) {
reject();
} else {
setTimeout(check.bind(null, n + 1), 100);
}
}
check(1);
});
}
}
customElements.define('liebs-picker-image', ImageListImageElement);