diff --git a/src/web/App.mjs b/src/web/App.mjs index 85b4f897..a8fa2b3e 100755 --- a/src/web/App.mjs +++ b/src/web/App.mjs @@ -66,8 +66,8 @@ class App { document.dispatchEvent(this.manager.appstart); this.loadLocalStorage(); - this.buildUI(); this.buildCategoryList(); + this.buildUI(); this.manager.setup(); this.manager.output.saveBombe(); this.uriParams = this.getURIParams(); @@ -427,23 +427,30 @@ class App { * @param {string[]} favourites */ updateFavourites(favourites) { + // @todo: probably need this elsewhere + // // Destroy the current list items we no longer need in the edit Favourites modal + // const operations = document.querySelectorAll("#editable-favourites ...."); + // listItems.forEach((li => { + // li.remove(); + // })) + this.saveFavourites(favourites); this.loadFavourites(); /* Rebuild only the favourites category */ - // double-check if the first category is indeed "catFavourites", if (document.querySelector("c-category-list > ul > c-category-li > li > a[data-target='#catFavourites']")) { // then destroy document.querySelectorAll("c-category-list > ul > c-category-li")[0].remove(); // and rebuild it - const favCatConfig = this.categories.find( catConfig => catConfig.name === "Favourites"); + const favCatConfig = this.categories.find(catConfig => catConfig.name === "Favourites"); const favouriteCategory = new CCategoryLi( this, favCatConfig, this.operations, - false + false, + true ); // finally prepend it to c-category-list @@ -777,7 +784,7 @@ class App { * Fires whenever the input or recipe changes in any way. * * @listens Manager#statechange - * @param {event} e + * @param {Event} e */ stateChange(e) { debounce(function() { @@ -890,17 +897,18 @@ class App { } /** - * @fires Manager#oplistcreate in nested c-category-li build() function + * @fires Manager#oplistcreate from nested c-category-li > c-operation-list build() function */ buildCategoryList() { const categoryList = new CCategoryList( this, this.categories, - this.operations + this.operations, + true ); categoryList.build(); - document.querySelector("#categories").appendChild( categoryList ); + document.querySelector("#categories").appendChild(categoryList); } } diff --git a/src/web/HTMLIngredient.mjs b/src/web/HTMLIngredient.mjs index 7eddb32c..2678de9b 100755 --- a/src/web/HTMLIngredient.mjs +++ b/src/web/HTMLIngredient.mjs @@ -319,7 +319,7 @@ class HTMLIngredient { * Handler for populate option changes. * Populates the relevant argument with the specified value. * - * @param {event} e + * @param {Event} e */ populateOptionChange(e) { e.preventDefault(); @@ -343,7 +343,7 @@ class HTMLIngredient { * Handler for populate multi option changes. * Populates the relevant arguments with the specified values. * - * @param {event} e + * @param {Event} e */ populateMultiOptionChange(e) { e.preventDefault(); @@ -374,7 +374,7 @@ class HTMLIngredient { * Handler for editable option clicks. * Populates the input box with the selected value. * - * @param {event} e + * @param {Event} e */ editableOptionClick(e) { e.preventDefault(); @@ -395,7 +395,7 @@ class HTMLIngredient { * Handler for argument selector changes. * Shows or hides the relevant arguments for this operation. * - * @param {event} e + * @param {Event} e */ argSelectorChange(e) { e.preventDefault(); diff --git a/src/web/Manager.mjs b/src/web/Manager.mjs index 758a8ae2..431b9210 100755 --- a/src/web/Manager.mjs +++ b/src/web/Manager.mjs @@ -151,12 +151,11 @@ class Manager { this.addMultiEventListener("#search", "keyup paste search click", this.ops.searchOperations, this.ops); this.addDynamicListener(".op-list li.operation", "dblclick", this.ops.operationDblclick, this.ops); document.getElementById("close-ops-dropdown-icon").addEventListener("click", this.ops.closeOpsDropdown.bind(this.ops)); - document.getElementById("edit-favourites").addEventListener("click", this.ops.editFavouritesClick.bind(this.ops)); + // document.getElementById("edit-favourites").addEventListener("click", this.ops.editFavouritesClick.bind(this.ops)); document.getElementById("save-favourites").addEventListener("click", this.ops.saveFavouritesClick.bind(this.ops)); document.getElementById("reset-favourites").addEventListener("click", this.ops.resetFavouritesClick.bind(this.ops)); this.addDynamicListener(".op-list", "oplistcreate", this.ops.opListCreate, this.ops); this.addDynamicListener("li.operation", "operationadd", this.recipe.opAdd, this.recipe); - // this.addDynamicListener(".op-icon.star-icon", "click", this.ops.onIconFavouriteClick, this.ops); // Recipe this.addDynamicListener(".arg:not(select)", "input", this.recipe.ingChange, this.recipe); diff --git a/src/web/components/c-category-li.mjs b/src/web/components/c-category-li.mjs index 705da1c4..24186492 100644 --- a/src/web/components/c-category-li.mjs +++ b/src/web/components/c-category-li.mjs @@ -1,4 +1,4 @@ -import {COperationLi} from "./c-operation-li.mjs"; +import {COperationList} from "./c-operation-list.mjs"; /** * c(ustom element)-category-li ( list item ) @@ -7,38 +7,66 @@ import {COperationLi} from "./c-operation-li.mjs"; * @param {CatConf} category - The category and operations to be populated. * @param {Object.} operations - The list of operation configuration objects. * @param {Boolean} isExpanded - expand the category on init or not + * @param {Boolean} includeOpLiStarIcon - Include the left side 'star' icon to favourite an operation easily * */ export class CCategoryLi extends HTMLElement { constructor( app, category, operations, - isExpanded + isExpanded, + includeOpLiStarIcon, ) { super(); this.app = app; - this.category = category; - this.operations = operations; + this.category = category; // contains a string[] of operation names under .ops + this.operations = operations; // opConfig[] this.label = category.name; this.isExpanded = isExpanded; + this.includeOpLiStarIcon = includeOpLiStarIcon; this.build(); this.addEventListener("click", this.handleClick.bind(this)); } - // /** - // * Handle click - // * - // * @param {Event} e - // */ - // handleClick(e) { - // if (e.target === this.querySelector("button")) { - // // todo back to this "hitbox" issue w the icon inside the button - // this.app.manager.ops.editFavouritesClick(e); - // } - // } + /** + * Handle click + * + * @param {Event} e + */ + handleClick(e) { + // todo some event (target ) bs here + if (e.target === this.querySelector("button")) { + // todo back to this "hitbox" issue w the icon inside the button + console.log(e.target); + this.app.manager.ops.editFavouritesClick(e); + } + } + + /** + * Build c-category-li containing a nested c-operation-list ( op-list ) + */ + build() { + const li = this.buildListItem(); + const a = this.buildAnchor(); + const div = this.buildCollapsablePanel(); + + li.appendChild(a); + li.appendChild(div); + this.appendChild(li); + + const opList = new COperationList( + this.app, + this.category.ops, + this.includeOpLiStarIcon, + ) + + opList.build(); + + div.appendChild(opList); + } /** * Build the li element @@ -101,53 +129,6 @@ export class CCategoryLi extends HTMLElement { return div; }; - /** - * Build the op-list for this category - * - * @param {string[]} opNames - */ - buildOperationList(opNames) { - return opNames.map(opName => { - if (!(opName in this.operations)) { - log.warn(`${opName} could not be found.`); - return; - } - - return new COperationLi( - this.app, - opName, - { - class: "check-icon", - innerText: "check" - }, - this.operations[opName] - ); - }); - } - - /** - * Build c-category-li and dispatch event oplistcreate - */ - build() { - const ul = document.createElement("ul"); - ul.classList.add("op-list"); - - const li = this.buildListItem(); - const a = this.buildAnchor(); - const div = this.buildCollapsablePanel(); - - li.appendChild(a); - li.appendChild(div); - div.appendChild(ul); - this.appendChild(li); - - this.buildOperationList(this.category.ops).forEach(operationListItem => - ul.appendChild(operationListItem) - ); - - ul.dispatchEvent(this.app.manager.oplistcreate); - } - /** * Append a c-operation-li to this op-list * diff --git a/src/web/components/c-category-list.mjs b/src/web/components/c-category-list.mjs index 2f259c94..bdd9c8f0 100644 --- a/src/web/components/c-category-list.mjs +++ b/src/web/components/c-category-list.mjs @@ -5,15 +5,17 @@ import {CCategoryLi} from "./c-category-li.mjs"; * * @param {App} app - The main view object for CyberChef * @param {CatConf[]} categories - The list of categories and operations to be populated. - * @param {Object.} operations - The list of operation configuration objects. + * @param {Object.} operations - A list of operation configuration objects. + * @param {boolean} includeOpLiStarIcon - optionally add the 'star' icon to the left of an individual operation **/ export class CCategoryList extends HTMLElement { - constructor( app, categories, operations ) { + constructor(app, categories, operations, includeOpLiStarIcon) { super(); this.app = app; this.categories = categories; this.operations = operations; + this.includeOpLiStarIcon = includeOpLiStarIcon; } /** @@ -27,9 +29,9 @@ export class CCategoryList extends HTMLElement { this.app, category, this.operations, - index === 0 + index === 0, + this.includeOpLiStarIcon ); - ul.appendChild(cat); }); diff --git a/src/web/components/c-operation-li.mjs b/src/web/components/c-operation-li.mjs index 716d5c70..fcc33171 100644 --- a/src/web/components/c-operation-li.mjs +++ b/src/web/components/c-operation-li.mjs @@ -6,22 +6,24 @@ import url from "url"; * @param {App} app - The main view object for CyberChef * @param {string} name - The name of the operation * @param {Object} icon - { class: string, innerText: string } - The optional and customizable icon displayed on the right side of the operation - * @param {Object} config - The configuration object for this operation. + * @param {Boolean} includeStarIcon - Include the left side 'star' icon to favourite an operation easily */ export class COperationLi extends HTMLElement { constructor( app, name, icon, - config + includeStarIcon, ) { super(); this.app = app; this.name = name; - this.isFavourite = this.app.isLocalStorageAvailable() && localStorage.favourites?.includes(name); this.icon = icon; - this.config = config; + this.includeStarIcon = includeStarIcon; + + this.config = this.app.operations[name]; + this.isFavourite = this.app.isLocalStorageAvailable() && localStorage.favourites?.includes(name); this.build(); @@ -29,6 +31,8 @@ export class COperationLi extends HTMLElement { this.addEventListener('dblclick', this.handleDoubleClick.bind(this)); } + // todo: dont think I need config separately, just use this.app.operations[name].xx? + /** * @fires OperationsWaiter#operationDblclick on double click * @param {Event} e @@ -50,6 +54,23 @@ export class COperationLi extends HTMLElement { } } + /** + * Build c-operation-li + */ + build() { + const li = this.buildListItem(); + const icon = this.buildIcon(); + + if ( this.includeStarIcon ){ + const starIcon = this.buildStarIcon(); + li.appendChild(starIcon); + } + + li.appendChild(icon); + + this.appendChild(li); + } + /** * Given a URL for a Wikipedia (or other wiki) page, this function returns a link to that page. * @@ -128,7 +149,7 @@ export class COperationLi extends HTMLElement { } /** - * Build the star icon + * Build the ( optional ) star icon */ buildStarIcon() { const icon = document.createElement("i"); @@ -147,20 +168,6 @@ export class COperationLi extends HTMLElement { return icon; } - /** - * Build c-operation-li - */ - build() { - const li = this.buildListItem(); - const icon = this.buildIcon(); - const starIcon = this.buildStarIcon(); - - li.appendChild(icon); - li.appendChild(starIcon); - - this.appendChild(li); - } - updateFavourite(isFavourite) { if (isFavourite) { this.querySelector("li").classList.add("favourite"); diff --git a/src/web/components/c-operation-list.mjs b/src/web/components/c-operation-list.mjs new file mode 100644 index 00000000..e0ad33c9 --- /dev/null +++ b/src/web/components/c-operation-list.mjs @@ -0,0 +1,45 @@ +import {COperationLi} from "./c-operation-li.mjs"; + +/** + * c(ustom element)-operation-list + * + * @param {App} app - The main view object for CyberChef + * @param {string[]} opNames - A list of operation names + * @param {boolean} includeStarIcon - optionally add the 'star' icon to the left of the operation + * @param {Object} icon ( { class: string, innerText: string } ). check-icon by default + */ +export class COperationList extends HTMLElement { + constructor(app, opNames, includeStarIcon, icon) { + super(); + + this.app = app; + this.opNames = opNames; + this.includeStarIcon = includeStarIcon; + this.icon = icon; + } + + build() { + const ul = document.createElement("ul"); + ul.classList.add("op-list"); + + this.opNames.forEach((opName => { + const li = new COperationLi( + this.app, + opName, + { + class: this.icon ? this.icon.class : "check-icon", + innerText: this.icon ? this.icon.innerText : "check" + }, + this.includeStarIcon + ); + + ul.appendChild(li); + })) + + ul.dispatchEvent(this.app.manager.oplistcreate); + + this.append(ul); + } +} + +customElements.define("c-operation-list", COperationList); diff --git a/src/web/html/index.html b/src/web/html/index.html index 4e7ec022..77647e2d 100755 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -142,14 +142,6 @@
- - - - - - - -