mirror of
https://github.com/gchq/CyberChef.git
synced 2025-05-11 08:41:32 -04:00
[#181] handle the correct resetting of layouts in any maximised pane situation, i.e. window resizing while panels are maximised etc. Prevent mobile keyboard popup window resize events to trigger layout resetting when panes are maximised, use JS to calculate the innerHeight available for mobile devices as they are of variable / unreliable / inconsistent heights
This commit is contained in:
parent
f80284cb36
commit
ee9ea051d1
10 changed files with 151 additions and 126 deletions
|
@ -419,90 +419,75 @@ ${navigator.userAgent}
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle the maximising and resetting to default state of
|
||||
* panels.
|
||||
* Maximise control button click handler.
|
||||
*
|
||||
* On mobile UI, #recipe, #input and #output can be maximised,
|
||||
* on desktop UI it's available only for #output
|
||||
* The buttons have IDs like 'maximise-input', 'maximise-output' etc. We grab the
|
||||
* to-be-maximised pane ID itself by stripping the pane ID from the button ID.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
handlePaneMaximising(e){
|
||||
// the event target btn can be one of ( currently ) 3 'maximiser' buttons
|
||||
const btn = e.target.classList.contains("btn-maximise") ? e.target : e.target.parentNode;
|
||||
// find the parent ( target ) pane to be maximised that belongs to the btn
|
||||
const pane = this.resolveMaximiserParentPane( btn.id )
|
||||
onMaximiseButtonClick(e) {
|
||||
// the target pane is not already maximised because it does not have the 'maximised-pane' class..
|
||||
const maximise = !document.getElementById(e.currentTarget.id.replace('maximise-', '')).classList.contains("maximised-pane");
|
||||
this.setPaneMaximised(e.currentTarget.id.replace('maximise-', ''), maximise);
|
||||
}
|
||||
|
||||
if (btn.getAttribute("data-original-title") === "Maximise pane") {
|
||||
this.maximisePane(btn,pane);
|
||||
/**
|
||||
* Handle the maximising ( and resetting to default state ) of
|
||||
* panes.
|
||||
*
|
||||
* @param {string} paneId
|
||||
* @param {boolean} maximise
|
||||
*/
|
||||
setPaneMaximised( paneId, maximise ){
|
||||
const pane = document.getElementById( paneId );
|
||||
const btn = document.getElementById( `maximise-${paneId}` );
|
||||
|
||||
this.setMaximiseControlButton(btn, maximise);
|
||||
this.setPaneMaximisedClasses(pane, maximise);
|
||||
|
||||
if ( maximise ) {
|
||||
pane.style.height = `${window.innerHeight - 40}px`;
|
||||
} else {
|
||||
this.resetPane(btn, pane);
|
||||
if ( window.innerWidth < this.app.breakpoint ){
|
||||
this.app.divideAvailableSpace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent pane of the 'maximise' button / icon that was
|
||||
* clicked through the buttons' ID
|
||||
* Set and remove the appropriate classes on maximise / minimise actions
|
||||
*
|
||||
* @param {string} id
|
||||
* @param {HTMLElement} pane
|
||||
* @param {boolean} maximise
|
||||
*/
|
||||
resolveMaximiserParentPane(id){
|
||||
switch(id) {
|
||||
case "maximise-recipe":
|
||||
return document.getElementById("recipe");
|
||||
case "maximise-input":
|
||||
return document.getElementById("input");
|
||||
case "maximise-output":
|
||||
return document.getElementById("output");
|
||||
setPaneMaximisedClasses(pane, maximise) {
|
||||
if ( maximise ) {
|
||||
pane.classList.add("top-zindex");
|
||||
pane.classList.add("maximised-pane");
|
||||
} else {
|
||||
pane.classList.remove("top-zindex");
|
||||
pane.classList.remove("maximised-pane");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pane from default state to Maximised
|
||||
*
|
||||
* @param {HTMLElement} btn
|
||||
* @param {HTMLElement} pane
|
||||
*/
|
||||
maximisePane(btn, pane){
|
||||
this.togglePane(pane,true);
|
||||
this.toggleIcon(btn, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the pane from Maximised state to default
|
||||
* Set the correct icon and data title attribute text based on
|
||||
* the 'maximise' flag
|
||||
*
|
||||
* @param {HTMLElement} btn
|
||||
* @param {HTMLElement} pane
|
||||
* @param {boolean} maximise
|
||||
*/
|
||||
resetPane(btn, pane) {
|
||||
this.togglePane(pane, false);
|
||||
this.toggleIcon(btn, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the pane to or from maximised size,
|
||||
* based on the 'isMaximised' flag
|
||||
*
|
||||
* @param {HTMLElement} pane
|
||||
* @param {boolean} isMaximised
|
||||
*/
|
||||
togglePane(pane, isMaximised) {
|
||||
isMaximised ? pane.classList.add("top-zindex") : pane.classList.remove("top-zindex");
|
||||
isMaximised ? pane.classList.add("maximised-pane") : pane.classList.remove("maximised-pane");
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the 'maximise' icon and attribute text based on
|
||||
* the 'isMaximised' flag
|
||||
*
|
||||
* @param {HTMLElement} btn
|
||||
* @param {boolean} isMaximised
|
||||
*/
|
||||
toggleIcon(btn, isMaximised ) {
|
||||
btn.querySelector("i").innerHTML = isMaximised ? "fullscreen_exit" : "fullscreen";
|
||||
$(btn).attr("data-original-title", isMaximised ? "Reset pane" : "Maximise pane");
|
||||
setMaximiseControlButton(btn, maximise ) {
|
||||
if ( maximise ) {
|
||||
btn.querySelector("i").innerHTML = "fullscreen_exit";
|
||||
btn.setAttribute("data-original-title", "Reset pane");
|
||||
} else {
|
||||
btn.querySelector("i").innerHTML = "fullscreen";
|
||||
btn.setAttribute("data-original-title", "Maximise pane");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,28 +15,61 @@ class WindowWaiter {
|
|||
* WindowWaiter constructor.
|
||||
*
|
||||
* @param {App} app - The main view object for CyberChef.
|
||||
* @param {Manager} manager - The CyberChef event manager.
|
||||
*/
|
||||
constructor(app) {
|
||||
constructor(app, manager) {
|
||||
this.app = app;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for window resize events.
|
||||
*
|
||||
* Resets adjustable component sizes after 200ms (so that continuous resizing doesn't cause
|
||||
* continuous resetting).
|
||||
*/
|
||||
windowResize() {
|
||||
if ( window.innerWidth >= this.app.breakpoint ) {
|
||||
this.app.setDesktopUI(false);
|
||||
this.onResizeToDesktop();
|
||||
} else {
|
||||
this.app.setMobileUI();
|
||||
this.onResizeToMobile();
|
||||
}
|
||||
|
||||
// #output can be maximised on all screen sizes, so if it was open while resizing,
|
||||
// it can be kept maximised until minimised manually
|
||||
if ( document.getElementById("output").classList.contains("maximised-pane") ) {
|
||||
this.manager.controls.setPaneMaximised( "output", true );
|
||||
}
|
||||
|
||||
debounce(this.app.adjustComponentSizes, 200, "windowResize", this.app, [])();
|
||||
}
|
||||
|
||||
|
||||
onResizeToDesktop(){
|
||||
this.app.setDesktopUI(false);
|
||||
|
||||
// if a window is resized past breakpoint while #recipe or #input is maximised,
|
||||
// the maximised pane is set to its default ( non-maximised ) state
|
||||
["recipe", "input"].forEach( paneId => this.manager.controls.setPaneMaximised(paneId, false));
|
||||
|
||||
// to prevent #recipe from keeping the height set in divideAvailableSpace
|
||||
document.getElementById("recipe").style.height = "100%";
|
||||
}
|
||||
|
||||
|
||||
onResizeToMobile(){
|
||||
this.app.setMobileUI();
|
||||
|
||||
// when mobile devices' keyboards pop up, it triggers a window resize event. Here
|
||||
// we keep the maximised panes open until the minimise button is clicked / tapped
|
||||
["recipe", "input", "output"]
|
||||
.map( paneId => document.getElementById(paneId))
|
||||
.filter( pane => pane.classList.contains("maximised-pane"))
|
||||
.forEach( pane => this.manager.controls.setPaneMaximised(pane.id, true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for window blur events.
|
||||
* Saves the current time so that we can calculate how long the window was unfocused for when
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue