mirror of
https://github.com/ONLYOFFICE/onlyoffice.github.io.git
synced 2026-02-10 18:05:06 +08:00
type checking
This commit is contained in:
@ -30,17 +30,31 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @typedef {import('../types.js').IconCategoryType} IconCategoryType */
|
||||
|
||||
class CategoriesPicker {
|
||||
#container;
|
||||
#onSelectCategoryCallback = () => {};
|
||||
/**
|
||||
* @param {string} category
|
||||
*/
|
||||
#onSelectCategoryCallback = (category) => {};
|
||||
#selectedCategory = "";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param {IconCategoryType[]} catalogOfIcons
|
||||
*/
|
||||
constructor(catalogOfIcons) {
|
||||
/** @type {HTMLDivElement} */
|
||||
this.#container = document.getElementById("categories");
|
||||
this.#addEventListener();
|
||||
this.#show(catalogOfIcons);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {IconCategoryType[]} catalogOfIcons
|
||||
*/
|
||||
#show(catalogOfIcons) {
|
||||
this.#selectedCategory = "";
|
||||
const fragment = document.createDocumentFragment();
|
||||
@ -60,52 +74,61 @@ class CategoriesPicker {
|
||||
categoryName.className = "category-name";
|
||||
});
|
||||
|
||||
this.#container.appendChild(fragment);
|
||||
this.#container?.appendChild(fragment);
|
||||
}
|
||||
|
||||
reset() {
|
||||
if (this.#selectedCategory !== "") {
|
||||
this.#selectedCategory = "";
|
||||
this.#container
|
||||
.querySelectorAll(".category.selected")
|
||||
.forEach((category) => {
|
||||
category.classList.remove("selected");
|
||||
});
|
||||
if (this.#selectedCategory === "") {
|
||||
return;
|
||||
}
|
||||
this.#selectedCategory = "";
|
||||
this.#container
|
||||
?.querySelectorAll(".category.selected")
|
||||
.forEach((category) => {
|
||||
category.classList.remove("selected");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the callback function to be called when a category is selected.
|
||||
* The callback function will receive the name of the selected category as a parameter.
|
||||
* @param {function} callback - The callback function to be called when a category is selected
|
||||
* @param {() => void} callback
|
||||
*/
|
||||
setOnSelectCategoryCallback(callback) {
|
||||
this.#onSelectCategoryCallback = callback;
|
||||
}
|
||||
|
||||
#addEventListener() {
|
||||
this.#container.addEventListener("click", (e) => {
|
||||
const categoryName = e.target.closest(".category-name");
|
||||
if (categoryName) {
|
||||
let id = categoryName.getAttribute("data-id");
|
||||
let category = categoryName.parentElement;
|
||||
let wasSelected = category.classList.contains("selected");
|
||||
this.#container?.addEventListener("click", (e) => {
|
||||
let categoryName;
|
||||
|
||||
this.#container
|
||||
.querySelectorAll(".category.selected")
|
||||
.forEach((category) => {
|
||||
category.classList.remove("selected");
|
||||
});
|
||||
|
||||
if (wasSelected) {
|
||||
category.classList.remove("selected");
|
||||
this.#selectedCategory = "";
|
||||
} else {
|
||||
category.classList.add("selected");
|
||||
this.#selectedCategory = id;
|
||||
}
|
||||
this.#onSelectCategoryCallback(this.#selectedCategory);
|
||||
const target = e.target;
|
||||
if (target && target instanceof HTMLElement) {
|
||||
categoryName = target.closest(".category-name");
|
||||
}
|
||||
|
||||
if (!categoryName) {
|
||||
return;
|
||||
}
|
||||
let id = categoryName.getAttribute("data-id");
|
||||
if (typeof id !== "string") {
|
||||
id = "";
|
||||
}
|
||||
let category = categoryName.parentElement;
|
||||
let wasSelected = category?.classList.contains("selected");
|
||||
|
||||
this.#container
|
||||
?.querySelectorAll(".category.selected")
|
||||
.forEach((category) => {
|
||||
category.classList.remove("selected");
|
||||
});
|
||||
|
||||
if (wasSelected) {
|
||||
category?.classList.remove("selected");
|
||||
this.#selectedCategory = "";
|
||||
} else {
|
||||
category?.classList.add("selected");
|
||||
this.#selectedCategory = id;
|
||||
}
|
||||
this.#onSelectCategoryCallback(this.#selectedCategory);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,24 +30,44 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @typedef {import('../types.js').IconCategoryType} IconCategoryType */
|
||||
|
||||
class IconPicker {
|
||||
#container;
|
||||
#onSelectIconCallback = () => {};
|
||||
/**
|
||||
* @param {Map<string, string>} map
|
||||
* @param {boolean} [needToRun]
|
||||
*/
|
||||
#onSelectIconCallback = (map, needToRun) => {};
|
||||
#listOfIconNames;
|
||||
#selectedIcons;
|
||||
#clearSelectionButton;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param {IconCategoryType[]} catalogOfIcons
|
||||
*/
|
||||
constructor(catalogOfIcons) {
|
||||
this.#listOfIconNames = new Set();
|
||||
this.#selectedIcons = new Map();
|
||||
this.#container = document.getElementById("icons");
|
||||
this.#clearSelectionButton = document.getElementById("clear");
|
||||
this.#addEventListener();
|
||||
this.show(catalogOfIcons);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {IconCategoryType[]} catalogOfIcons
|
||||
* @param {string} categoryId
|
||||
*/
|
||||
show(catalogOfIcons, categoryId = "") {
|
||||
this.#listOfIconNames = new Set();
|
||||
this.#selectedIcons = new Map();
|
||||
this.#container.textContent = "";
|
||||
if (this.#container) {
|
||||
this.#container.textContent = "";
|
||||
}
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
catalogOfIcons.forEach((categoryInfo) => {
|
||||
@ -72,21 +92,29 @@ class IconPicker {
|
||||
this.#onChange();
|
||||
});
|
||||
|
||||
this.#container.appendChild(fragment);
|
||||
this.#container?.appendChild(fragment);
|
||||
|
||||
if (this.#listOfIconNames.size === 0) {
|
||||
if (this.#listOfIconNames.size === 0 && this.#container) {
|
||||
this.#container.textContent =
|
||||
"Your search didn't match any content. Please try another term.";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {() => void} callback
|
||||
*/
|
||||
setOnSelectIconCallback(callback) {
|
||||
this.#onSelectIconCallback = callback;
|
||||
}
|
||||
|
||||
#addEventListener() {
|
||||
this.#container.addEventListener("click", (e) => {
|
||||
const icon = e.target.closest(".icon");
|
||||
this.#container?.addEventListener("click", (e) => {
|
||||
let icon;
|
||||
const target = e.target;
|
||||
if (target && target instanceof HTMLElement) {
|
||||
icon = target.closest(".icon");
|
||||
}
|
||||
|
||||
if (icon) {
|
||||
const isModifierPressed = e.ctrlKey || e.metaKey;
|
||||
|
||||
@ -106,22 +134,28 @@ class IconPicker {
|
||||
this.#onChange();
|
||||
}
|
||||
});
|
||||
this.#container.addEventListener("dblclick", (e) => {
|
||||
const icon = e.target.closest(".icon");
|
||||
if (icon) {
|
||||
let iconId = icon.getAttribute("data-name");
|
||||
let section = icon.getAttribute("data-section");
|
||||
icon.classList.add("selected");
|
||||
this.#selectedIcons.set(iconId, section);
|
||||
const needToRun = true;
|
||||
this.#onSelectIconCallback(this.#selectedIcons, needToRun);
|
||||
this.#container?.addEventListener("dblclick", (e) => {
|
||||
let icon;
|
||||
const target = e.target;
|
||||
if (target && target instanceof HTMLElement) {
|
||||
icon = target.closest(".icon");
|
||||
}
|
||||
|
||||
if (!icon) {
|
||||
return;
|
||||
}
|
||||
let iconId = icon.getAttribute("data-name");
|
||||
let section = icon.getAttribute("data-section");
|
||||
icon.classList.add("selected");
|
||||
this.#selectedIcons.set(iconId, section);
|
||||
const needToRun = true;
|
||||
this.#onSelectIconCallback(this.#selectedIcons, needToRun);
|
||||
});
|
||||
this.#clearSelectionButton.addEventListener(
|
||||
this.#clearSelectionButton?.addEventListener(
|
||||
"click",
|
||||
this.#unselectAll.bind(this, false)
|
||||
);
|
||||
this.#container.addEventListener("keydown", (e) => {
|
||||
this.#container?.addEventListener("keydown", (e) => {
|
||||
if ((e.ctrlKey || e.metaKey) && e.code === "KeyA") {
|
||||
e.preventDefault();
|
||||
this.#selectAll();
|
||||
@ -131,7 +165,7 @@ class IconPicker {
|
||||
|
||||
#selectAll() {
|
||||
this.#container
|
||||
.querySelectorAll(".icon:not(.selected)")
|
||||
?.querySelectorAll(".icon:not(.selected)")
|
||||
.forEach((icon) => {
|
||||
let iconId = icon.getAttribute("data-name");
|
||||
let section = icon.getAttribute("data-section");
|
||||
@ -143,7 +177,7 @@ class IconPicker {
|
||||
|
||||
#unselectAll(silent = false) {
|
||||
this.#selectedIcons = new Map();
|
||||
this.#container.querySelectorAll(".icon.selected").forEach((icon) => {
|
||||
this.#container?.querySelectorAll(".icon.selected").forEach((icon) => {
|
||||
icon.classList.remove("selected");
|
||||
});
|
||||
if (silent) return;
|
||||
@ -153,14 +187,20 @@ class IconPicker {
|
||||
#onChange() {
|
||||
const total = this.#listOfIconNames.size;
|
||||
const selected =
|
||||
this.#container.querySelectorAll(".icon.selected").length;
|
||||
document.getElementById(
|
||||
"total"
|
||||
).textContent = `${total} icons, ${selected} selected`;
|
||||
this.#container?.querySelectorAll(".icon.selected").length;
|
||||
const totalElement = document.getElementById("total");
|
||||
if (totalElement) {
|
||||
totalElement.textContent = `${total} icons, ${selected} selected`;
|
||||
}
|
||||
|
||||
this.#onSelectIconCallback(this.#selectedIcons);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} iconId
|
||||
* @param {string} section
|
||||
* @returns
|
||||
*/
|
||||
#createIcon(iconId, section) {
|
||||
const svgNS = "http://www.w3.org/2000/svg";
|
||||
const xlinkNS = "http://www.w3.org/1999/xlink";
|
||||
@ -172,7 +212,7 @@ class IconPicker {
|
||||
svg.setAttribute("role", "img");
|
||||
svg.setAttribute("data-name", iconId);
|
||||
svg.setAttribute("data-section", section);
|
||||
svg.setAttribute("tabindex", 0);
|
||||
svg.setAttribute("tabindex", "0");
|
||||
|
||||
const title = document.createElementNS(svgNS, "title");
|
||||
svg.appendChild(title);
|
||||
|
||||
@ -30,37 +30,64 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @typedef {import('../types.js').IconCategoryType} IconCategoryType */
|
||||
|
||||
class SearchFilter {
|
||||
#catalogOfIcons;
|
||||
#filteredCatalog;
|
||||
#onFilterCallback;
|
||||
|
||||
/**
|
||||
* @param {IconCategoryType[]} catalogOfIcons
|
||||
*/
|
||||
constructor(catalogOfIcons) {
|
||||
this.#onFilterCallback = (
|
||||
/** @type {IconCategoryType[]} */ categories
|
||||
) => {};
|
||||
this.#filteredCatalog = catalogOfIcons;
|
||||
this.#catalogOfIcons = catalogOfIcons;
|
||||
this.input = document.getElementById("searchFilter");
|
||||
this.input.addEventListener("input", this.#onInput.bind(this));
|
||||
this.input?.addEventListener(
|
||||
"input",
|
||||
this.#onInput.bind(this, this.input)
|
||||
);
|
||||
}
|
||||
|
||||
reset() {
|
||||
if (this.input instanceof HTMLInputElement === false) {
|
||||
return;
|
||||
}
|
||||
if (this.input.value !== "") {
|
||||
this.input.value = "";
|
||||
this.#filteredCatalog = this.#catalogOfIcons;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {() => {}} callback
|
||||
*/
|
||||
setOnFilterCallback(callback) {
|
||||
this.#onFilterCallback = callback;
|
||||
}
|
||||
|
||||
#onInput(e) {
|
||||
const value = e.target.value.slice().toLowerCase();
|
||||
/**
|
||||
* @param {HTMLElement} input
|
||||
*/
|
||||
#onInput(input) {
|
||||
if (input instanceof HTMLInputElement === false) {
|
||||
return;
|
||||
}
|
||||
let value = input.value.slice().toLowerCase();
|
||||
if (value === "") {
|
||||
this.#filteredCatalog = this.#catalogOfIcons;
|
||||
} else {
|
||||
this.#filteredCatalog = this.#catalogOfIcons
|
||||
.slice()
|
||||
.map((categoryInfo) => {
|
||||
let filteredIcons = [];
|
||||
/** @type {[string[]]} */
|
||||
let filteredIcons = [[]];
|
||||
|
||||
categoryInfo.folders.forEach((folderName, index) => {
|
||||
let icons = categoryInfo.icons[index];
|
||||
|
||||
13
sdkjs-plugins/content/icons/src/js/types.js
Normal file
13
sdkjs-plugins/content/icons/src/js/types.js
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @typedef {'brands' | 'regular' | 'solid'} FolderType
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} IconCategoryType
|
||||
* @property {string} id
|
||||
* @property {string} label
|
||||
* @property {FolderType[]} folders
|
||||
* @property {[string[]]} icons
|
||||
*/
|
||||
|
||||
export {};
|
||||
Reference in New Issue
Block a user