Public
Edited
Apr 22
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof all = TaggedImageSearcher();
Insert cell
function TaggedImageSearcher() {
const countInput = Inputs.number({
label: "How many images do you want to upload?",
min: 1,
max: 10,
step: 1,
value: 1
});

const generateButton = htl.html`<button>Generate Image Uploaders</button>`;
const uploadersContainer = htl.html`<div style="margin-top: 1em;"></div>`;
const showAllButton = htl.html`<button>Show Collection</button>`;
const displayContainer = htl.html`<div style="margin-top: 1em;"></div>`;

const checkboxButton = htl.html`<button>Generate Checkboxes</button>`;
const searchContainer = htl.html`<div style="margin-top: 1em;"></div>`;
const resultButton = htl.html`<button>Show Results</button>`;
const resultContainer = htl.html`<div style="margin-top: 1em;"></div>`;

const wrapper = htl.html`<div>
<h3>Upload Images</h3>
${countInput}
${generateButton}
${uploadersContainer}
<hr>
<h3>Display Collection</h3>
${showAllButton}
${displayContainer}
<hr>
<h3>Search checkboxes</h3>
${checkboxButton}
${searchContainer}
${resultButton}
${resultContainer}
<hr>
</div>`;

let widgetTemp = []; // store references to all ImageTagAdder widgets

let widgetsData = { // store complete widgets data {file, tags}
widgets: [],
allTags: []
};

async function showValue() {
// to match ReactiveWidget structure
}

generateButton.onclick = () => {
uploadersContainer.innerHTML = "";
widgetTemp = [];

const n = countInput.value;
for (let i = 0; i < n; i++) {
const label = htl.html`<h4>Image ${i + 1}</h4>`;
const widget = ImageTagAdder();
widgetTemp.push(widget);
uploadersContainer.appendChild(htl.html`<div style="margin-bottom: 2em;">${label}${widget}</div>`);
}
};

showAllButton.onclick = async () => {
displayContainer.innerHTML = "";
const n = countInput.value;
try {
for (let j = 0; j < n; j++) {
widgetsData.widgets.push(widgetTemp[j].value);
const imageTags = widgetTemp[j].value.tags.forEach((t) => {
widgetsData.allTags.push(t);
});
}
} catch (error) {
console.error("Error saving widgets data!");
}
displayContainer.appendChild(htl.html`<div>
Tags collection:
${widgetsData.allTags.join(", ")}
</div>`);
};

let selected;
checkboxButton.onclick = () => {
searchContainer.innerHTML = "";
selected = searchCheckbox(
widgetsData.allTags,
{
// value: null,
label: "Image Tags",
}
);
searchContainer.appendChild(htl.html`<div style="margin-top: 1em;">${selected}</div>`);
const mostTag = mostFrequentTag(widgetsData.allTags);
searchContainer.appendChild(htl.html`<div>Most frequent tag: ${mostTag}</div>`);
}

resultButton.onclick = async () => {
resultContainer.innerHTML = "";
const tagList = selected.value || [];
if (tagList.length === 0) {
resultContainer.appendChild(html`<div>Please select at least one tag.</div>`);
return;
}
const flatData = widgetsData.widgets;
const n = widgetsData.widgets.length;
for (let i = 0; i < n; i++) {
const filterFlag = flatData[i].tags.some(item => tagList.includes(item));
if (filterFlag) {
const image = await htl.html`<div>${await flatData[i].file.image()}</div>`;
resultContainer.appendChild(htl.html`<div style="display: flex; flex-wrap: wrap; gap: 1em;">
${image}
</div>`);
}
}
};

function mostFrequentTag(list) {
const result = aq.table({ tag: list })
.groupby("tag")
.count()
.orderby(aq.desc("count"))
.objects()[0];
return result.tag;
}

const result = ReactiveWidget(wrapper, {
value: widgetsData,
showValue
});
return result;

};

Insert cell
import { aq, op } from '@uwdata/arquero'
Insert cell
import {ImageTagAdder} from "@lang-min-neu/photo-tag-adder"
Insert cell
import {ReactiveWidget} from "@john-guerra/reactive-widgets"
Insert cell
import {searchCheckbox} from "@john-guerra/search-checkbox"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more