Output tabs now (mostly) work.

Add downloading files as an archive (needs work)
Add option for keeping the tabs in sync
This commit is contained in:
j433866 2019-04-03 12:00:47 +01:00
parent e0c9aba25e
commit 9df26b8c84
6 changed files with 236 additions and 35 deletions

View file

@ -554,7 +554,7 @@ class InputWaiter {
this.setFile(inputNum);
}
}
this.changeTab(inputNum);
this.changeTab(inputNum, this.app.options.syncTabs);
}
/**
@ -778,7 +778,7 @@ class InputWaiter {
if (numTabs > 0) {
tabsWrapper.parentElement.style.display = "block";
const tabButtons = document.getElementsByClassName("tab-buttons");
const tabButtons = document.getElementsByClassName("input-tab-buttons");
for (let i = 0; i < tabButtons.length; i++) {
tabButtons.item(i).style.display = "inline-block";
}
@ -850,7 +850,7 @@ class InputWaiter {
if (newInputs.length > 1) {
tabsList.parentElement.style.display = "block";
const tabButtons = document.getElementsByClassName("tab-buttons");
const tabButtons = document.getElementsByClassName("input-tab-buttons");
for (let i = 0; i < tabButtons.length; i++) {
tabButtons.item(i).style.display = "inline-block";
}
@ -861,7 +861,7 @@ class InputWaiter {
} else {
tabsList.parentElement.style.display = "none";
const tabButtons = document.getElementsByClassName("tab-buttons");
const tabButtons = document.getElementsByClassName("input-tab-buttons");
for (let i = 0; i < tabButtons.length; i++) {
tabButtons.item(i).style.display = "none";
}
@ -877,7 +877,7 @@ class InputWaiter {
}
this.changeTab(activeTab);
this.manager.output.refreshTabs(activeTab);
// MAKE THE OUTPUT REFRESH TOO
}
@ -960,8 +960,9 @@ class InputWaiter {
* Changes the active tab
*
* @param {number} inputNum
* @param {boolean} [changeOutput=false]
*/
changeTab(inputNum) {
changeTab(inputNum, changeOutput = false) {
const currentNum = this.getActiveTab();
if (this.getInputIndex(inputNum) === -1) return;
@ -1002,6 +1003,10 @@ class InputWaiter {
this.setFile(inputNum);
}
if (changeOutput) {
this.manager.output.changeTab(inputNum, false);
}
}
/**
@ -1015,7 +1020,7 @@ class InputWaiter {
}
const tabNum = mouseEvent.srcElement.parentElement.getAttribute("inputNum");
if (tabNum) {
this.changeTab(parseInt(tabNum, 10));
this.changeTab(parseInt(tabNum, 10), this.app.options.syncTabs);
}
}
@ -1026,9 +1031,9 @@ class InputWaiter {
const currentTab = this.getActiveTab();
const currentInput = this.getInputIndex(currentTab);
if (currentInput > 0) {
this.changeTab(this.getPreviousInputNum(currentTab));
this.changeTab(this.getPreviousInputNum(currentTab), this.app.options.syncTabs);
} else {
this.changeTab(this.inputs[0].inputNum);
this.changeTab(this.inputs[0].inputNum, this.app.options.syncTabs);
}
}
@ -1037,7 +1042,7 @@ class InputWaiter {
*/
changeTabRight() {
const currentTab = this.getActiveTab();
this.changeTab(this.getNextInputNum(currentTab));
this.changeTab(this.getNextInputNum(currentTab), this.app.options.syncTabs);
}
/**
@ -1046,7 +1051,7 @@ class InputWaiter {
goToTab() {
const tabNum = parseInt(window.prompt("Enter tab number:", this.getActiveTab().toString()), 10);
if (this.getInputIndex(tabNum)) {
this.changeTab(tabNum);
this.changeTab(tabNum, this.app.options.syncTabs);
}
}
@ -1065,6 +1070,21 @@ class InputWaiter {
return largest;
}
/**
* Gets the smallest inputNum
*
* @returns {number}
*/
getSmallestInputNum() {
let smallest = this.getLargestInputNum();
for (let i = 0; i < this.inputs.length; i++) {
if (this.inputs[i].inputNum < smallest) {
smallest = this.inputs[i].inputNum;
}
}
return smallest;
}
/**
* Gets the previous inputNum
*
@ -1138,7 +1158,7 @@ class InputWaiter {
*/
clearAllIoClick() {
for (let i = this.inputs.length - 1; i >= 0; i--) {
this.removeInput(this.inputs[i].inputNum);
this.removeTab(this.inputs[i].inputNum);
}
this.refreshTabs();
}

View file

@ -158,14 +158,15 @@ class Manager {
// this.addMultiEventListener("#input-text", "mousedown dblclick select", this.highlighter.inputMousedown, this.highlighter);
document.querySelector("#input-file .close").addEventListener("click", this.input.clearIoClick.bind(this.input));
document.getElementById("btn-new-tab").addEventListener("click", this.input.addTab.bind(this.input));
document.getElementById("btn-previous-tab").addEventListener("click", this.input.changeTabLeft.bind(this.input));
document.getElementById("btn-next-tab").addEventListener("click", this.input.changeTabRight.bind(this.input));
document.getElementById("btn-go-to-tab").addEventListener("click", this.input.goToTab.bind(this.input));
document.getElementById("btn-previous-input-tab").addEventListener("click", this.input.changeTabLeft.bind(this.input));
document.getElementById("btn-next-input-tab").addEventListener("click", this.input.changeTabRight.bind(this.input));
document.getElementById("btn-go-to-input-tab").addEventListener("click", this.input.goToTab.bind(this.input));
this.addDynamicListener("#input-tabs li .btn-close-tab i", "click", this.input.removeTabClick, this.input);
this.addDynamicListener("#input-tabs li .input-tab-content", "click", this.input.changeTabClick, this.input);
// Output
// document.getElementById("save-to-file").addEventListener("click", this.output.saveClick.bind(this.output));
document.getElementById("save-to-file").addEventListener("click", this.output.saveClick.bind(this.output));
document.getElementById("save-all-to-file").addEventListener("click", this.output.saveAllClick.bind(this.output));
// document.getElementById("copy-output").addEventListener("click", this.output.copyClick.bind(this.output));
// document.getElementById("switch").addEventListener("click", this.output.switchClick.bind(this.output));
// document.getElementById("undo-switch").addEventListener("click", this.output.undoSwitchClick.bind(this.output));
@ -183,6 +184,9 @@ class Manager {
// document.getElementById("show-file-overlay").addEventListener("click", this.output.showFileOverlayClick.bind(this.output));
// this.addDynamicListener(".extract-file,.extract-file i", "click", this.output.extractFileClick, this.output);
this.addDynamicListener("#output-tabs-wrapper #output-tabs li .output-tab-content", "click", this.output.changeTabClick, this.output);
document.getElementById("btn-previous-output-tab").addEventListener("click", this.output.changeTabLeft.bind(this.output));
document.getElementById("btn-next-output-tab").addEventListener("click", this.output.changeTabRight.bind(this.output));
document.getElementById("btn-go-to-output-tab").addEventListener("click", this.output.goToTab.bind(this.output));
// Options
document.getElementById("options").addEventListener("click", this.options.optionsClick.bind(this.options));

View file

@ -7,6 +7,9 @@
import Utils from "../core/Utils";
import FileSaver from "file-saver";
import zip from "zlibjs/bin/zip.min";
const Zlib = zip.Zlib;
/**
* Waiter to handle events related to the output
@ -31,16 +34,17 @@ class OutputWaiter {
* Gets the output for the specified input number
*
* @param {number} inputNum
* @returns {Object}
* @returns {string | ArrayBuffer}
*/
getOutput(inputNum) {
const index = this.getOutputIndex(inputNum);
if (index === -1) return -1;
if (typeof this.outputs[index].data.result === "string") {
return this.outputs[index].data.result;
log.error(this.outputs[index]);
if (typeof this.outputs[index].data.dish.value === "string") {
return this.outputs[index].data.dish.value;
} else {
return this.outputs[index].data.result || "";
return this.outputs[index].data.dish.value || "";
}
}
@ -65,7 +69,7 @@ class OutputWaiter {
* @returns {string | ArrayBuffer}
*/
getActive() {
return this.getOutput(this.getActiveTab()).data;
return this.getOutput(this.getActiveTab());
}
/**
@ -124,7 +128,6 @@ class OutputWaiter {
* @param {number} inputNum
*/
updateOutputMessage(statusMessage, inputNum) {
// log.error(`MSG: ${statusMessage}; inputNum: ${inputNum}`);
const index = this.getOutputIndex(inputNum);
if (index === -1) return;
@ -371,6 +374,54 @@ class OutputWaiter {
}
}
/**
* Handler for save click events.
* Saves the current output to a file.
*/
saveClick() {
this.downloadFile(this.getActiveTab());
}
/**
* Handler for file download events.
*/
async downloadFile() {
const fileName = window.prompt("Please enter a filename: ", "download.dat");
const file = new File([this.getActive()], fileName);
FileSaver.saveAs(file, fileName, false);
}
/**
* Handler for save all click event
* Saves all outputs to a single archvie file
*/
saveAllClick() {
this.downloadAllFiles();
}
/**
* Handler for download all files events.
*/
async downloadAllFiles() {
const fileName = window.prompt("Please enter a filename: ", "download.zip");
const fileExt = window.prompt("Please enter a file extension for the files: ", ".txt");
const zip = new Zlib.Zip();
for (let i = 0; i < this.outputs.length; i++) {
const name = Utils.strToByteArray(this.outputs[i].inputNum + fileExt);
log.error(this.getOutput(this.outputs[i].inputNum));
let out = this.getOutput(this.outputs[i].inputNum);
if (typeof out === "string") {
out = Utils.strToUtf8ByteArray(out);
}
out = new Uint8Array(out);
log.error(out);
// options.filename = Utils.strToByteArray(this.outputs[i].inputNum + ".dat");
zip.addFile(out, {filename: name});
}
const file = new File([zip.compress()], fileName);
FileSaver.saveAs(file, fileName, false);
}
/**
* Adds a new output tab.
*
@ -389,7 +440,11 @@ class OutputWaiter {
if (numTabs > 0) {
tabsWrapper.parentElement.style.display = "block";
// output tab buttons?
const tabButtons = document.getElementsByClassName("output-tab-buttons");
for (let i = 0; i < tabButtons.length; i++) {
tabButtons.item(i).style.display = "inline-block";
}
document.getElementById("output-wrapper").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
document.getElementById("output-highlighter").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
@ -399,7 +454,7 @@ class OutputWaiter {
}
if (changeTab) {
this.changeTab(inputNum);
this.changeTab(inputNum, false);
}
}
@ -407,8 +462,9 @@ class OutputWaiter {
* Changes the active tab
*
* @param {number} inputNum
* @param {boolean} [changeInput = false]
*/
changeTab(inputNum) {
changeTab(inputNum, changeInput = false) {
const currentNum = this.getActiveTab();
if (this.getOutputIndex(inputNum) === -1) return;
@ -435,12 +491,16 @@ class OutputWaiter {
tabs.item(i).setAttribute("inputNum", newOutputs[i].toString());
this.displayTabInfo(newOutputs[i]);
if (newOutputs[i] === inputNum) {
tabs.item(i).classList.add("active-input-tab");
tabs.item(i).classList.add("active-output-tab");
}
}
}
this.set(inputNum);
if (changeInput) {
this.manager.input.changeTab(inputNum, false);
}
}
/**
@ -452,7 +512,38 @@ class OutputWaiter {
if (!mouseEvent.srcElement) return;
const tabNum = mouseEvent.srcElement.parentElement.getAttribute("inputNum");
if (tabNum) {
this.changeTab(parseInt(tabNum, 10));
this.changeTab(parseInt(tabNum, 10), this.app.options.syncTabs);
}
}
/**
* Handler for changing to the left tab
*/
changeTabLeft() {
const currentTab = this.getActiveTab();
const currentOutput = this.getOutputIndex(currentTab);
if (currentOutput > 0) {
this.changeTab(this.getPreviousInputNum(currentTab), this.app.options.syncTabs);
} else {
this.changeTab(this.getSmallestInputNum(), this.app.options.syncTabs);
}
}
/**
* Handler for changing to the right tab
*/
changeTabRight() {
const currentTab = this.getActiveTab();
this.changeTab(this.getNextInputNum(currentTab), this.app.options.syncTabs);
}
/**
* Handler for go to tab button clicked
*/
goToTab() {
const tabNum = parseInt(window.prompt("Enter tab number:", this.getActiveTab().toString()), 10);
if (this.getOutputIndex(tabNum)) {
this.changeTab(tabNum, this.app.options.syncTabs);
}
}
@ -532,6 +623,21 @@ class OutputWaiter {
return largest;
}
/**
* Gets the smallest inputNum
*
* @returns {number}
*/
getSmallestInputNum() {
let smallest = this.getLargestInputNum();
for (let i = 0; i < this.outputs.length; i++) {
if (this.outputs[i].inputNum < smallest) {
smallest = this.outputs[i].inputNum;
}
}
return smallest;
}
/**
* Gets the previous inputNum
*
@ -539,7 +645,7 @@ class OutputWaiter {
* @returns {number}
*/
getPreviousInputNum(inputNum) {
let num = -1;
let num = this.getSmallestInputNum();
for (let i = 0; i < this.outputs.length; i++) {
if (this.outputs[i].inputNum < inputNum) {
if (this.outputs[i].inputNum > num) {
@ -574,6 +680,7 @@ class OutputWaiter {
* @param {number} inputNum
*/
removeTab(inputNum) {
let activeTab = this.getActiveTab();
if (this.getOutputIndex(inputNum) === -1) return;
const tabElement = this.getTabItem(inputNum);
@ -582,9 +689,67 @@ class OutputWaiter {
if (tabElement !== null) {
// find new tab number?
if (inputNum === activeTab) {
activeTab = this.getPreviousInputNum(activeTab);
if (activeTab === this.getActiveTab()) {
activeTab = this.getNextInputNum(activeTab);
}
}
this.refreshTabs(activeTab);
}
}
/**
* Redraw the entire tab bar to remove any outdated tabs
* @param {number} activeTab
*/
refreshTabs(activeTab) {
const tabsList = document.getElementById("output-tabs");
let newInputs = this.getNearbyNums(activeTab, "right");
if (newInputs.length < this.maxTabs) {
newInputs = this.getNearbyNums(activeTab, "left");
}
for (let i = tabsList.children.length - 1; i >= 0; i--) {
tabsList.children.item(i).remove();
}
for (let i = 0; i < newInputs.length; i++) {
tabsList.appendChild(this.createTabElement(newInputs[i]));
this.displayTabInfo(newInputs[i]);
}
if (newInputs.length > 1) {
tabsList.parentElement.style.display = "block";
const tabButtons = document.getElementsByClassName("output-tab-buttons");
for (let i = 0; i < tabButtons.length; i++) {
tabButtons.item(i).style.display = "inline-block";
}
document.getElementById("output-wrapper").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
document.getElementById("output-highlighter").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
document.getElementById("output-file").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
document.getElementById("output-loader").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
} else {
tabsList.parentElement.style.display = "none";
const tabButtons = document.getElementsByClassName("output-tab-buttons");
for (let i = 0; i < tabButtons.length; i++) {
tabButtons.item(i).style.display = "none";
}
document.getElementById("output-wrapper").style.height = "calc(100% - var(--title-height))";
document.getElementById("output-highlighter").style.height = "calc(100% - var(--title-height))";
document.getElementById("output-file").style.height = "calc(100% - var(--title-height))";
document.getElementById("output-loader").style.height = "calc(100% - var(--title-height))";
}
this.changeTab(activeTab);
}
/**
* Creates a new tab element to be added to the tab bar
*

View file

@ -229,13 +229,13 @@
<div class="title no-select">
<label for="input-text">Input</label>
<span class="float-right">
<button type="button" class="btn btn-primary bmd-btn-icon tab-buttons" id="btn-previous-tab" data-toggle="tooltip" title="Go to the previous tab">
<button type="button" class="btn btn-primary bmd-btn-icon input-tab-buttons" id="btn-previous-input-tab" data-toggle="tooltip" title="Go to the previous tab">
<i class="material-icons">keyboard_arrow_left</i>
</button>
<button type="button" class="btn btn-primary bmd-btn-icon tab-buttons" id="btn-go-to-tab" data-toggle="tooltip" title="Go to a specific tab">
<button type="button" class="btn btn-primary bmd-btn-icon input-tab-buttons" id="btn-go-to-input-tab" data-toggle="tooltip" title="Go to a specific tab">
<i class="material-icons">more_horiz</i>
</button>
<button type="button" class="btn btn-primary bmd-btn-icon tab-buttons" id="btn-next-tab" data-toggle="tooltip" title="Go to the next tab">
<button type="button" class="btn btn-primary bmd-btn-icon input-tab-buttons" id="btn-next-input-tab" data-toggle="tooltip" title="Go to the next tab">
<i class="material-icons">keyboard_arrow_right</i>
</button>
<button type="button" class="btn btn-primary bmd-btn-icon" id="btn-new-tab" data-toggle="tooltip" title="Add a new input tab">
@ -285,15 +285,18 @@
<div class="title no-select">
<label for="output-text">Output</label>
<span class="float-right">
<button type="button" class="btn btn-primary bmd-btn-icon tab-buttons" id="btn-previous-tab" data-toggle="tooltip" title="Go to the previous tab">
<button type="button" class="btn btn-primary bmd-btn-icon output-tab-buttons" id="btn-previous-output-tab" data-toggle="tooltip" title="Go to the previous tab">
<i class="material-icons">keyboard_arrow_left</i>
</button>
<button type="button" class="btn btn-primary bmd-btn-icon tab-buttons" id="btn-go-to-tab" data-toggle="tooltip" title="Go to a specific tab">
<button type="button" class="btn btn-primary bmd-btn-icon output-tab-buttons" id="btn-go-to-output-tab" data-toggle="tooltip" title="Go to a specific tab">
<i class="material-icons">more_horiz</i>
</button>
<button type="button" class="btn btn-primary bmd-btn-icon tab-buttons" id="btn-next-tab" data-toggle="tooltip" title="Go to the next tab">
<button type="button" class="btn btn-primary bmd-btn-icon output-tab-buttons" id="btn-next-output-tab" data-toggle="tooltip" title="Go to the next tab">
<i class="material-icons">keyboard_arrow_right</i>
</button>
<button type="button" class="btn btn-primary bmd-btn-icon output-tab-buttons" id="save-all-to-file" data-toggle="tooltip" title="Save all outputs to a file">
<i class="material-icons">archive</i>
</button>
<button type="button" class="btn btn-primary bmd-btn-icon" id="save-to-file" data-toggle="tooltip" title="Save output to file">
<i class="material-icons">save</i>
</button>
@ -551,6 +554,13 @@
Render a preview of the input if it's detected to be an image.
</label>
</div>
<div class="checkbox option-item">
<label for="syncTabs">
<input type="checkbox" option="syncTabs" id="syncTabs">
Keep the current tab in sync between the input and output.
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" id="reset-options">Reset options to default</button>

View file

@ -53,6 +53,7 @@ function main() {
logLevel: "info",
autoMagic: true,
imagePreview: true,
syncTabs: true
};
document.removeEventListener("DOMContentLoaded", main, false);

View file

@ -85,7 +85,8 @@
background-color: var(--primary-background-colour);
}
.tab-buttons {
.input-tab-buttons,
.output-tab-buttons {
transition: 1s all ease;
display: none;
}