191 lines
5.6 KiB
JavaScript
191 lines
5.6 KiB
JavaScript
import { api } from "../../scripts/api.js";
|
|
import { Segments } from "./Segments.js";
|
|
|
|
/**
|
|
* A list of images to display and their selected state.
|
|
*/
|
|
export class ImageList extends EventTarget {
|
|
|
|
constructor(imageList) {
|
|
super();
|
|
|
|
this.items = [];
|
|
for (let i = 0; i < imageList.length; i++) {
|
|
let item = {
|
|
url: imageList[i].url,
|
|
segments: new Segments(imageList[i].segments),
|
|
selected: false,
|
|
unwanted: false
|
|
};
|
|
|
|
this.items.push(item);
|
|
|
|
// Propagate events from the image segments.
|
|
item.segments.addEventListener('segment-change', event => {
|
|
this.dispatchEvent(new CustomEvent('segment-change', {
|
|
detail: {
|
|
imageList: this,
|
|
image: item,
|
|
index: i,
|
|
segn: event.detail.segn,
|
|
label: event.detail.label,
|
|
unwanted: event.detail.unwanted
|
|
}
|
|
}));
|
|
});
|
|
}
|
|
}
|
|
|
|
get length() {
|
|
return this.items.length;
|
|
}
|
|
|
|
// Count selected items in the list.
|
|
get selectedCount() {
|
|
let count = 0;
|
|
for (const image of this.items) {
|
|
if (image.selected) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
// Get an array of the selected indexes.
|
|
get selectedIndexes() {
|
|
let result = []
|
|
for (let i = 0; i < this.items.length; i++) {
|
|
if (this.items[i].selected) {
|
|
result.push(i);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Count wanted items in the list.
|
|
get wantedCount() {
|
|
let count = 0;
|
|
for (const image of this.items) {
|
|
if (!image.unwanted) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
// True if the image at index is selected, otherwise false.
|
|
isSelected(index) {
|
|
return this.items[index].selected;
|
|
}
|
|
|
|
// Select or de-select the image at index.
|
|
select(index, value) {
|
|
this.items[index].selected = value;
|
|
this.dispatchEvent(new CustomEvent('image-select', {
|
|
detail: {
|
|
imageList: this,
|
|
index,
|
|
selected: value,
|
|
unwnated: this.items[index].unwanted
|
|
}
|
|
}));
|
|
}
|
|
|
|
// Toggle selection of the image at index.
|
|
toggleSelect(index) {
|
|
const selected = this.items[index].selected;
|
|
this.select(index, !selected);
|
|
return selected;
|
|
}
|
|
|
|
// Get the URL for the image at index.
|
|
getImageUrl (index) {
|
|
const url = this.items[index].url;
|
|
return api.apiURL(`/view?filename=${encodeURIComponent(url.filename)}&type=${url.type ?? "input"}&subfolder=${url.subfolder ?? ""}&r=${Math.random()}`);
|
|
}
|
|
|
|
// True if the image at index is unwanted, otherwise false.
|
|
isUnwanted(index) {
|
|
return this.items[index].unwanted;
|
|
}
|
|
|
|
// Want or unwant the image at index.
|
|
unwanted(index, value) {
|
|
this.items[index].unwanted = value;
|
|
this.dispatchEvent(new CustomEvent('image-unwanted', {
|
|
detail: {
|
|
imageList: this,
|
|
index,
|
|
selected: this.items[index].selected,
|
|
unwanted: value
|
|
}
|
|
}));
|
|
}
|
|
|
|
// Toggle unwanted of the image at index.
|
|
toggleUnwanted(index) {
|
|
const unwanted = !this.items[index].unwanted;
|
|
this.unwanted(index, unwanted);
|
|
return unwanted;
|
|
}
|
|
|
|
// Get the segment information for the image at index.
|
|
getImageSegments(index) {
|
|
return this.items[index].segments;
|
|
}
|
|
|
|
// Applied a selection by selecting or unwanting by index.
|
|
selectAndLock(selected, locked) {
|
|
if (selected === 'all') {
|
|
for (const item of this.items) {
|
|
item.selected = !locked;
|
|
}
|
|
} else
|
|
if (selected === 'none') {
|
|
for (const item of this.items) {
|
|
item.selected = false;
|
|
}
|
|
} else {
|
|
// Parse the selection into an array of indexes.
|
|
selected = selected.split(',')
|
|
.map(i => Number.parseInt(i))
|
|
.filter(i => Number.isFinite(i))
|
|
// Convert 1-based list to 0-based index.
|
|
.map(i => i - 1)
|
|
.filter(i => (i >= 0) && (i < this.items.length))
|
|
|
|
if (selected.length) {
|
|
// When the selection is locked, instead of picking the selected items - unwant the unselected items.
|
|
for (let i = 0; i < this.items.length; i++) {
|
|
let isSelected = selected.includes(i);
|
|
if (isSelected && !locked) {
|
|
this.select(i, true);
|
|
} else
|
|
if (!isSelected && locked) {
|
|
this.unwanted(i, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Get the list of images to pass and segment labels.
|
|
getResult() {
|
|
const result = []
|
|
const filterMode = this.selectedCount === 0;
|
|
for (const [i, item] of Object.entries(this.items)) {
|
|
if (item.selected || (filterMode && !item.unwanted)) {
|
|
result.push({
|
|
index: Number(i),
|
|
segments: {
|
|
label: item.segments.getResult()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
}
|