treehouse/static/js/dev/picture-upload.js

150 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class PictureUpload extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.tabIndex = 0;
this.gotoInit();
this.preview = this.querySelector("img[name='preview']");
this.addEventListener("click", (event) => {
if (event.target == this || event.target.parentElement == this) {
event.preventDefault();
this.focus();
}
});
this.addEventListener("paste", async (event) => {
if (event.clipboardData.items.length != 1) {
console.error("only one item is supported");
return;
}
let item = event.clipboardData.items[0];
await this.paste(item);
});
}
gotoInit() {
this.setState("init");
this.innerHTML = `
<div class="nothing-pasted">
paste or drop an image here to make a picture out of it
</div>
`;
}
async gotoHavePicture(imageType, imageFile) {
this.setState("have-picture");
this.innerHTML = `
<div class="have-picture">
<img name="preview" class="pic" alt="preview">
<p>
<span name="preview-width"></span> × <span name="preview-height"></span> px (<span name="file-size"></span>)
</p>
<p>
<label for="label">label</label>
<input name="label" type="text" placeholder="untitled"></input>
</p>
<p>
<label for="compression">compression</label>
<select name="compression">
<option value="Lossless">lossless</option>
</select>
</p>
<button name="upload">upload</button>
</div>
`;
let preview = this.querySelector("img[name='preview']");
let previewWidth = this.querySelector("[name='preview-width']");
let previewHeight = this.querySelector("[name='preview-height']");
let fileSize = this.querySelector("[name='file-size']");
let label = this.querySelector("[name='label']");
let compression = this.querySelector("[name='compression']");
let upload = this.querySelector("button[name='upload']");
fileSize.textContent = formatSizeSI(imageFile.size);
let url = URL.createObjectURL(imageFile);
preview.src = url;
createImageBitmap(imageFile).then((bitmap) => {
console.log(bitmap);
previewWidth.textContent = bitmap.width.toString();
previewHeight.textContent = bitmap.height.toString();
});
upload.addEventListener("click", async () => {
let params = new URLSearchParams({
label: label.value,
format: imageType,
compression: compression.value,
});
let response = await fetch(`/dev/picture-upload?${params}`, {
method: "POST",
body: imageFile,
});
let json = await response.json();
if (json.error != null) {
console.error(json.error);
} else {
await navigator.clipboard.writeText(json.ulid);
await this.gotoCopiedToClipboard();
}
});
}
async gotoCopiedToClipboard() {
this.setState("copied-to-clipboard");
this.innerHTML = `
<div class="copied-to-clipboard">ulid copied to clipboard; the window will now refresh</div>
`;
}
setState(name) {
this.setAttribute("data-state", name);
}
async paste(item) {
console.log(item);
if (!isSupportedImageType(item.type)) {
console.error("unsupported mime type", item.type);
return;
}
let file = item.getAsFile();
if (file == null) {
console.error("data transfer does not contain a file");
return;
}
await this.gotoHavePicture(item.type, file);
}
}
customElements.define("th-picture-upload", PictureUpload);
function isSupportedImageType(mime) {
return (
mime == "image/png" ||
mime == "image/jpeg" ||
mime == "image/svg+xml" ||
mime == "image/webp"
);
}
function formatSizeSI(bytes) {
return new Intl.NumberFormat(undefined, {
style: "unit",
unit: "byte",
notation: "compact",
unitDisplay: "narrow",
}).format(bytes);
}