├── images
├── dd.gif
├── pin.gif
├── header.png
├── search_nodes.gif
├── expand_collapse.gif
├── search_categories.gif
└── YouTube.svg
├── __init__.py
├── LICENSE
├── README.md
├── .gitignore
└── js
└── sidebar_node.js
/images/dd.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZHO-ZHO-ZHO/ComfyUI-N-Sidebar-ZHO/HEAD/images/dd.gif
--------------------------------------------------------------------------------
/images/pin.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZHO-ZHO-ZHO/ComfyUI-N-Sidebar-ZHO/HEAD/images/pin.gif
--------------------------------------------------------------------------------
/images/header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZHO-ZHO-ZHO/ComfyUI-N-Sidebar-ZHO/HEAD/images/header.png
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | NODE_CLASS_MAPPINGS = {}
2 | NODE_DISPLAY_NAME_MAPPINGS = {}
3 |
4 |
5 |
6 | WEB_DIRECTORY = "./js"
--------------------------------------------------------------------------------
/images/search_nodes.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZHO-ZHO-ZHO/ComfyUI-N-Sidebar-ZHO/HEAD/images/search_nodes.gif
--------------------------------------------------------------------------------
/images/expand_collapse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZHO-ZHO-ZHO/ComfyUI-N-Sidebar-ZHO/HEAD/images/expand_collapse.gif
--------------------------------------------------------------------------------
/images/search_categories.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZHO-ZHO-ZHO/ComfyUI-N-Sidebar-ZHO/HEAD/images/search_categories.gif
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 pythongosssss
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/images/YouTube.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # 我自己改了一版 ComfyPark 配色(我就喜欢 ALL BLACK )
5 |
6 |
7 |
8 | 
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | # 以下是原作者内容:
20 |
21 |
22 |
23 |
24 | 
25 |
26 |
27 |
28 | [](https://www.youtube.com/channel/UCnu819ZX2xiusPpbQ4KzSmA)
29 |
30 | # ComfyUI-N-Sidebar
31 | A simple sidebar for ComfyUI.
32 | For what i know nobody did it, so i did it.
33 | Maybe you don't need it. I need it >.<
34 |
35 | # Installation
36 |
37 | 1. Clone the repository:
38 | `git clone https://github.com/Nuked88/ComfyUI-N-Sidebar.git`
39 | to your ComfyUI `custom_nodes` directory
40 | 2. Enjoy!
41 |
42 |
43 | # Uninstall
44 | - Delete the `ComfyUI-N-Sidebar` folder in `custom_nodes`
45 |
46 |
47 | # Update
48 | 1. Navigate to the cloned repo e.g. `custom_nodes/ComfyUI-N-Sidebar`
49 | 2. `git pull`
50 |
51 | # Features
52 |
53 |
54 | ### 🖱️Drag and Drop Nodes🖱️
55 | 
56 |
57 |
58 | ### 📌Pin Your Favorite Node📌
59 | 
60 |
61 | ### 🔍Search within your nodes📄
62 | 
63 |
64 | ### 🔍Search within categories📂
65 | 
66 |
67 | ### ➕Expand/Collapse Categories/Sidebar➖
68 | 
69 |
70 | ## Contributing
71 |
72 | Feel free to contribute to this project by reporting issues or suggesting improvements. Open an issue or submit a pull request on the GitHub repository.
73 |
74 | ## Donations
75 |
76 | If you'd like to support the project, consider making a donation ❤️
77 |
78 | [](https://ko-fi.com/C0C0AJECJ)
79 |
80 | ## License
81 |
82 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
83 |
84 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # poetry
98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102 | #poetry.lock
103 |
104 | # pdm
105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106 | #pdm.lock
107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108 | # in version control.
109 | # https://pdm.fming.dev/#use-with-ide
110 | .pdm.toml
111 |
112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113 | __pypackages__/
114 |
115 | # Celery stuff
116 | celerybeat-schedule
117 | celerybeat.pid
118 |
119 | # SageMath parsed files
120 | *.sage.py
121 |
122 | # Environments
123 | .env
124 | .venv
125 | env/
126 | venv/
127 | ENV/
128 | env.bak/
129 | venv.bak/
130 |
131 | # Spyder project settings
132 | .spyderproject
133 | .spyproject
134 |
135 | # Rope project settings
136 | .ropeproject
137 |
138 | # mkdocs documentation
139 | /site
140 |
141 | # mypy
142 | .mypy_cache/
143 | .dmypy.json
144 | dmypy.json
145 |
146 | # Pyre type checker
147 | .pyre/
148 |
149 | # pytype static type analyzer
150 | .pytype/
151 |
152 | # Cython debug symbols
153 | cython_debug/
154 |
155 | # PyCharm
156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158 | # and can be added to the global gitignore or merged into this file. For a more nuclear
159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160 | #.idea/
--------------------------------------------------------------------------------
/js/sidebar_node.js:
--------------------------------------------------------------------------------
1 | import { $el } from "../../../scripts/ui.js";
2 |
3 | let categorySearchToggle = false;
4 | function addSidebarStyles() {
5 | const sidebarStyle = `
6 | .litegraph .dialog {
7 | z-index: 100 !important;
8 | }
9 |
10 | .sidebar {
11 | position: absolute;
12 | top: 0;
13 | left: -250px;
14 | width: fit-content;
15 | height: calc(100% - 19px);
16 |
17 | color: white;
18 | transition: left 0.3s ease;
19 | z-index: 2;
20 | overflow: hidden;
21 |
22 | padding-top: 19px;
23 | left: 0;
24 | user-select: none;
25 |
26 | }
27 |
28 | .sidebar ul {
29 | list-style-type: none;
30 |
31 | border-bottom: 2px solid #FF96AC;
32 | background: #000000;
33 | padding-left: 5px;
34 | padding-right: 5px;
35 | }
36 | .sidebar li {
37 | padding: 10px;
38 | cursor: pointer;
39 | user-select: none;
40 | }
41 |
42 | .content_sidebar {
43 | background-color: #000000;
44 | overflow-y: auto;
45 | overflow-x: hidden;
46 | height: 100%;
47 | float:left;
48 | backdrop-filter: blur(5px);
49 | }
50 |
51 | .dragHandle {
52 | position: relative;
53 | float: left;
54 | right: 0;
55 | top: 0;
56 | height: 100%;
57 | width: 10px;
58 | cursor: ew-resize;
59 | background: rgb(62,62,62);
60 | background: linear-gradient(90deg, rgb(62 62 62 / 46%) 0%, rgb(39 39 39 / 47%) 50%, rgb(28 28 28 / 31%) 100%);
61 | }
62 | #searchInput {
63 | box-sizing: border-box;
64 | width: 100%;
65 | border-radius: 5px;
66 | padding: 10px;
67 | border: none;
68 | user-select: none;
69 | background: #000000;
70 | color: #fff;
71 |
72 | }
73 | .sidebar-header {
74 | position: absolute;
75 | width: calc(100% - 49px);
76 | margin-top: 5px;
77 | margin-bottom: 10px;
78 | margin-left: 10px;
79 |
80 | z-index: 400;
81 |
82 | }
83 | .clearIcon,.searchCategoryIcon{
84 | position: absolute;
85 | padding: 5px;
86 | right: 30px;
87 | color: #fff;
88 | font-size: x-large;
89 | cursor: pointer;
90 | opacity: 0.5;
91 | user-select: none;
92 | }
93 |
94 |
95 | .clearIcon:hover{
96 | opacity: 1.0;
97 | }
98 |
99 | .searchCategoryIcon{
100 | right: 0px;
101 | padding: 3px;
102 | font-size: larger;
103 | background: #000000;
104 | color: #fff;
105 | margin: 4px;
106 | border-radius: 5px;
107 | width: 18px;
108 | text-align: center;
109 | top: 0;
110 |
111 |
112 | }
113 |
114 | .searchCategoryIcon:hover{
115 | opacity: 0.5;
116 | }
117 |
118 | .sidebarCategory, #sidebarBookmarks{
119 | list-style-type: none;
120 | font-family: 'Open Sans',sans-serif;
121 | text-transform: capitalize;
122 | margin: 2px;
123 | background-color: #000000;
124 | border-radius: 9px;
125 | padding-top: 11px;
126 | font-size: 15px;
127 | }
128 | .sidebarCategory:hover{
129 | background-color: #232323;
130 | }
131 | .sidebarItem:hover{
132 | background-color: #3a3a3a;
133 | }
134 | .sidebarItem {
135 | list-style-type: none;
136 | font-family: 'Open Sans',sans-serif;
137 | text-transform: capitalize;
138 | margin: 2px;
139 | background: #000000;
140 | border-radius: 8px;
141 |
142 | white-space: nowrap;
143 | text-overflow: ellipsis;
144 | overflow: hidden;
145 | max-width: calc(100% - 39px);
146 | }
147 |
148 |
149 | .content_sidebar::-webkit-scrollbar {
150 | margin-top: 0.5rem;
151 | height: 1rem;
152 | width: .5rem;
153 | top: 10px;
154 | }
155 |
156 | .content_sidebar::-webkit-scrollbar:horizontal {
157 | height: .5rem;
158 | width: 1rem
159 | }
160 |
161 | .content_sidebar::-webkit-scrollbar-track {
162 | background-color: transparent;
163 | border-radius: 9999px
164 | }
165 |
166 | .content_sidebar::-webkit-scrollbar-thumb {
167 | --tw-border-opacity: 1;
168 | background-color: hsla(0,0%,50%,.8);
169 | border-color: rgba(255,255,255,0,0,0);
170 | border-radius: 9999px;
171 | border-width: 1px
172 | }
173 |
174 | .content_sidebar::-webkit-scrollbar-thumb:hover {
175 | --tw-bg-opacity: 1;
176 | background-color: rgba(150,150,150,var(--tw-bg-opacity))
177 | }
178 | #spacer {
179 | height: 45px;
180 | }
181 |
182 | #switch_sidebar {
183 | position: relative;
184 | float: left;
185 | left: 0;
186 | margin-left: -0.6rem;
187 | cursor: pointer;
188 | user-select: none;
189 | padding: 2px;
190 | font-size: 20px;
191 | background-color: #000000;
192 | border-bottom-right-radius: 5px;
193 | border-top-right-radius: 5px;
194 |
195 | }
196 | #searchInput.closed {
197 | display: none;
198 | }
199 | #content_sidebar.closed {
200 | width: 0 !important;
201 | }
202 | .searchCategoryIcon.closed {
203 | display: none;
204 | }
205 | .clearIcon.closed {
206 | display: none;
207 | }
208 |
209 | .sidebarCategory .pinButton {
210 | background-color: transparent;
211 | border: 0;
212 | position: absolute;
213 | right: 0;
214 | }
215 |
216 | #sidebarBookmarks .pinButton {
217 |
218 | background-color: transparent;
219 | border: 0;
220 |
221 | position: absolute;
222 | right: 0;
223 | }
224 | .pinned{
225 | fill: #FF96AC !important;
226 | opacity: 1 !important;
227 | }
228 | .svg_class{
229 | width: 24px;
230 | height: 24px;
231 | fill: #353535;
232 | cursor: pointer;
233 | /* hacky fix */
234 | margin-top: -5px;
235 | margin-left: -25px;
236 | }
237 |
238 | .pin_normal{
239 | opacity: 0.5;
240 | }
241 | .pin_normal:hover{
242 | opacity: 1;
243 | }
244 | .svg_class:hover{
245 | fill: #4e4e4e;
246 |
247 | }
248 |
249 |
250 | #sidebarBookmarks .sidebarItem {
251 | margin-left: 10px;
252 | margin-right: 29px;
253 |
254 | }
255 | .sb_label {
256 | font-family: 'Open Sans',sans-serif;
257 | position: relative;
258 | margin: 5px;
259 | font-weight: bold;
260 |
261 | background: #000000;
262 | /* border: 2px solid; */
263 | border-radius: 3px;
264 | padding-left: 6px;
265 | padding-right: 6px;
266 | display: block;
267 | width: calc(100% - 20px);
268 | text-align: center;
269 | user-select: none;
270 | }
271 |
272 | .expand_node, .pin_node{
273 | position: absolute;
274 | right: 5px;
275 | background: transparent;
276 | border: 0;
277 |
278 | }
279 | .expand_node svg , .pin_node svg {
280 |
281 | width: 20px;
282 | height: 20px;
283 | background: transparent;
284 | fill: white;
285 | cursor: pointer;
286 | }
287 |
288 |
289 |
290 |
291 | `;
292 |
293 | const styleElement = $el("style", {
294 | parent: document.head,
295 | textContent: sidebarStyle
296 | });
297 | }
298 |
299 | function getCookie(name) {
300 | const cookies = document.cookie.split(';');
301 | for (const cookie of cookies) {
302 | const [cookieName, cookieValue] = cookie.trim().split('=');
303 | if (cookieName === name) {
304 | return cookieValue;
305 | }
306 | }
307 | return null;
308 | }
309 |
310 | function setCookie(name, value, days) {
311 | let expires = '';
312 | if (days) {
313 | const date = new Date();
314 | date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
315 | expires = '; expires=' + date.toUTCString();
316 | }
317 | document.cookie = name + '=' + value + expires + '; path=/';
318 | }
319 |
320 | function sidebarAddNode(name, text, x, y) {
321 | const node = LiteGraph.createNode(name, text)
322 | if (node) {
323 | const pos =
324 | [
325 | x,
326 | y
327 | ]
328 | node.pos = pos;
329 | app.graph.add(node)
330 | }
331 | }
332 |
333 | function saveSidebarWidth(sideb) {
334 | const width = sideb.style.width;
335 |
336 |
337 | document.cookie = setCookie("sidebarWidth", width, 3000);
338 | }
339 |
340 |
341 | function restoreSidebarWidth() {
342 | let width_sidebar = "auto";
343 | let cookieValue = getCookie("sidebarWidth");
344 | if (cookieValue) {
345 |
346 | width_sidebar = cookieValue;
347 | }
348 | return width_sidebar;
349 | }
350 |
351 |
352 | function savePinnedItems(pinnedItems) {
353 | const pinnedItemsString = JSON.stringify(pinnedItems);
354 | setCookie('pinnedItems', pinnedItemsString, 9999);
355 | }
356 |
357 |
358 | function loadPinnedItems() {
359 | const pinnedItemsString = getCookie('pinnedItems');
360 | if (pinnedItemsString) {
361 | return JSON.parse(pinnedItemsString);
362 | }
363 | return [];
364 | }
365 |
366 |
367 | function pinItem(itemId) {
368 |
369 | const item = document.getElementById(itemId);
370 | const sidebarBookmarks = document.getElementById("sidebarBookmarks");
371 | const pinnedItems = loadPinnedItems();
372 | if (!pinnedItems.includes(itemId)) {
373 | let addedItem = sidebarBookmarks.appendChild(item.cloneNode(true));
374 |
375 | addedItem.lastChild.lastChild.childNodes[1].classList.add("pinned");
376 | pinnedItems.push(itemId);
377 | savePinnedItems(pinnedItems);
378 | }
379 |
380 | }
381 |
382 |
383 |
384 | function unpinItem(itemId) {
385 | const item = document.getElementById(itemId);
386 | const sidebarBookmarks = document.getElementById("sidebarBookmarks");
387 | const pinnedItems = loadPinnedItems();
388 | if (pinnedItems.includes(itemId)) {
389 | sidebarBookmarks.removeChild(item);
390 | pinnedItems.splice(pinnedItems.indexOf(itemId), 1);
391 | savePinnedItems(pinnedItems);
392 | }
393 | }
394 |
395 |
396 | function removePinnedClass(itemId) {
397 |
398 | const sidebarItems = document.querySelectorAll(".sidebarItem");
399 |
400 |
401 | sidebarItems.forEach(function (item) {
402 |
403 | if (item.id === itemId) {
404 |
405 | const path = item.querySelector("path");
406 | if (path) {
407 | path.classList.remove("pinned");
408 | }
409 | }
410 | });
411 | }
412 |
413 |
414 | function loadPinnedItemsAndAddToBookmarks() {
415 | const pinnedItems = loadPinnedItems();
416 |
417 |
418 | const sidebarBookmarks = document.getElementById("sidebarBookmarks");
419 | pinnedItems.forEach(itemId => {
420 | pinItem(itemId);
421 | const item = document.getElementById(itemId);
422 | if (item) {
423 | let addedItem = sidebarBookmarks.appendChild(item.cloneNode(true));
424 |
425 | addedItem.lastChild.lastChild.classList.add("pinned");
426 |
427 | }
428 | });
429 | }
430 |
431 | function sdExpandAll() {
432 |
433 | const categoryItems = document.querySelectorAll(".content_sidebar .sidebarCategory");
434 | const side_bar_status = document.querySelector(".content_sidebar").dataset.expanded;
435 | const expand_node = document.getElementsByClassName("expand_node")[0];
436 |
437 | let display_value = "true";
438 |
439 | if (side_bar_status === "true") {
440 |
441 | display_value = "none";
442 | expand_node.innerHTML = ``;
453 | document.querySelector(".content_sidebar").dataset.expanded = "false";
454 |
455 | } else {
456 |
457 | display_value = "block";
458 | expand_node.innerHTML = ``;
467 | document.querySelector(".content_sidebar").dataset.expanded = "true";
468 |
469 | }
470 |
471 |
472 | categoryItems.forEach(function (categoryItem) {
473 | const displayNamesList = categoryItem.querySelector("ul");
474 |
475 | if (expand_node) {
476 |
477 |
478 | displayNamesList.style.display = display_value;
479 | }
480 |
481 | });
482 | }
483 |
484 |
485 |
486 | function createCategoryList() {
487 | const data = LiteGraph.registered_node_types;
488 | const categories = {};
489 | const pinnedItems = loadPinnedItems();
490 | for (const objKey in data) {
491 | const category = data[objKey].category;
492 | if (!categories[category]) {
493 | categories[category] = [];
494 | }
495 | categories[category].push(data[objKey]);
496 | }
497 |
498 |
499 | const sortedCategories = Object.keys(categories).sort();
500 |
501 |
502 | const sortedCategoriesData = {};
503 | sortedCategories.forEach(category => {
504 | sortedCategoriesData[category] = categories[category];
505 | });
506 |
507 | const categoriesList = document.getElementById("content_sidebar");
508 |
509 | for (const category in sortedCategoriesData) {
510 | const categoryItem = document.createElement("li");
511 | categoryItem.classList.add("sidebarCategory");
512 | categoryItem.textContent = category;
513 |
514 | const displayNamesList = document.createElement("ul");
515 | displayNamesList.style.display = "none";
516 | categoryItem.appendChild(displayNamesList);
517 |
518 | categories[category].forEach(displayName => {
519 | try {
520 | const displayNameItem = document.createElement("li");
521 | displayNameItem.classList.add("sidebarItem");
522 | displayNameItem.textContent = displayName.title;
523 | displayNameItem.title = displayName.title;
524 | displayNameItem.draggable = true;
525 |
526 | displayNameItem.id = displayName.type;
527 |
528 |
529 | const pinButton = document.createElement("button");
530 | pinButton.classList.add("pinButton");
531 |
532 | let add_class = "";
533 |
534 | if (pinnedItems.includes(displayName.type)) {
535 | add_class = "pinned";
536 | }
537 | pinButton.innerHTML = ``;
541 |
542 |
543 | displayNameItem.appendChild(pinButton);
544 |
545 | displayNamesList.appendChild(displayNameItem);
546 | } catch (err) {
547 |
548 | }
549 | });
550 |
551 | categoryItem.addEventListener("click", function (event) {
552 |
553 | if (event.target === event.currentTarget) {
554 |
555 | displayNamesList.style.display = displayNamesList.style.display === "none" ? "block" : "none";
556 | }
557 | });
558 |
559 |
560 | categoriesList.appendChild(categoryItem);
561 | }
562 |
563 |
564 | const dragHandle = document.getElementById("dragHandle");
565 |
566 | let isDragging = false;
567 | let startX;
568 | let startWidth;
569 |
570 |
571 | dragHandle.addEventListener("mousedown", function (event) {
572 | isDragging = true;
573 | startX = event.clientX;
574 | startWidth = parseInt(window.getComputedStyle(categoriesList).width);
575 |
576 | });
577 |
578 |
579 | document.addEventListener("mouseup", function () {
580 |
581 | if (isDragging) {
582 | isDragging = false;
583 |
584 | saveSidebarWidth(categoriesList);
585 |
586 | }
587 | });
588 |
589 |
590 | document.addEventListener("mousemove", function (event) {
591 | if (!isDragging) return;
592 |
593 | const delta = event.clientX - startX;
594 | categoriesList.style.width = (startWidth + delta) + "px";
595 | });
596 |
597 | loadPinnedItemsAndAddToBookmarks();
598 | }
599 |
600 | function addSidebar() {
601 |
602 | let draggedElementId;
603 | const sidebar_width = restoreSidebarWidth();
604 | const sidebarHtml = `
605 |