Объявление

В связи с наплывом спама и ботов на форуме, регистрация новых пользователей будет приостановлена. О восстановлении регистрации будет сообщено дополнительно

Administrator

№17351Вчера 23:56:47

Ki_rrrilll
Участник
 
Группа: Members
Зарегистрирован: 22-11-2013
Сообщений: 132
UA: Firefox 115.0

Re: Custom Buttons

yup пишет
Ki_rrrilll пишет

Как открыть папку с закладкой по имени этой закладки или по имени папки?

Задача не столь проста, как кажется. Советую найти старое расширение "Go Parent Folder" и посмотреть, как оно работает.


Главная проблема в том, что скрипту доступны только те элементы дерева закладок, которые видны в данный момент. Если нужные закладка или папка находятся внутри  свёрнутой папки, до них так просто не добраться.

Ну я все равно не разберусь как работает то расширение. И  UCF я не использую.
Сейчас я открываю папку с закладкой кодом

Выделить код

Код:

PlacesUtils.bookmarks.fetch(guid, null, {includePath: true})
  .then(res => PlacesCommandHook.showPlacesOrganizer(["AllBookmarks", ...res.path.map(b => b.guid), guid]))

А guid беру из резервной копии закладок в формате json. Ни о каких "живых" результатах конечно и речи нет, ну хоть как то.
Так вот я думал, может можно из этого json получать guid, по ключевому слову закладки? И желательно имя родительской папки.
Потому что я не очень умею обращаться с этими json и сейчас выуживаю нужный guid путем многочисленных split-ов, отсекая ненужное.

Отредактировано Ki_rrrilll (Сегодня 00:02:27)

Отсутствует

 

№17352Сегодня 02:23:48

yup
Участник
 
Группа: Members
Зарегистрирован: 15-04-2016
Сообщений: 1135
UA: Seamonkey 2.49

Re: Custom Buttons

Ki_rrrilll пишет

А guid беру из резервной копии закладок в формате json.

А что является критерием для поиска этого GUID? Имя закладки, URL, метка, ключевое слово или что?


Ki_rrrilll пишет

Так вот я думал, может можно из этого json получать guid, по ключевому слову закладки? И желательно имя родительской папки.
Потому что я не очень умею обращаться с этими json и сейчас выуживаю нужный guid путем многочисленных split-ов, отсекая ненужное.

Если преобразовать JSON в объект (а это просто один вызов функции JSON.parse(str)), то можно прогуляться по получившемуся дереву и найти в нём нужный элемент. А заодно в процессе этой прогулки и путь к закладке построится.


Только вот алгоритм прохода по дереву абсолютно аналогичен алгоритму, который используется скрипте SidebarBookmarkSearchOpenFolder. Зато скрипт не нуждается в JSON-е, он напрямую с данными окна работает.


И ещё мне кажется, что если в поиске информации о нужной закладке используется человек, то, наверное, имеет смысл взять ранее упомянутое расширение "Go Parent Folder" и засунуть его в кнопку. Потому что работает расширение так: ткнулись мышкой в нужную закладку, выбрали из её контекстного меню пункт "Go Parent Folder" - и происходит переход в папку, в которой где эта закладка лежит. А слева, соответственно, дерево до этой папки разворачивается и папка выбирается (становится текущей).
А  SidebarBookmarkSearchOpenFolder делает то же самое, только не в окне, а в боковой панели.


Ki_rrrilll пишет

И  UCF я не использую.

В кнопку данный скрипт засовывается с минимальными усилиями.

Отредактировано yup (Сегодня 02:44:26)

Отсутствует

 

№17353Сегодня 07:55:52

leex
Участник
 
Группа: Members
Зарегистрирован: 24-03-2011
Сообщений: 331
UA: Firefox 138.0

Re: Custom Buttons

Всем привет!
Если вы используете это расширение, отличные новости — с помощью ИИ удалось устранить баги, возникшие при работе в Firefox 138.
Теперь расширение снова работает корректно.

Оригинальный код был создан Dumby и отлично себя показал в более ранних версиях браузера.
Новая версия кода базируется на том же исходнике, но адаптирована под последние изменения Firefox.

Финальная версия доступна здесь:

скрытый текст

Выделить код

Код:

// ==UserScript==
// @name        Иконки поисковых систем из расширения ContextSearch-web-ext в контекстном меню
// @namespace   cswem
// @version     2.1
// @description Редактирует контекстное меню Firefox
// @match       *://*/*
// @grant       none
// @icon        https://www.mozilla.org/favicon.ico
// ==/UserScript==

(function() {
    'use strict';
    
    // Конфигурация
    const SETTINGS = {
        initializedFlag: 'cswemInitialized',  // Флаг инициализации
        menuId: 'cswem-menugroup',           // ID группы меню
        styleId: 'cswem-styles',             // ID стилей
        hiddenItems: [                       // Элементы для скрытия
            '_5dd73bb9-e728-4d1e-990b-c77d8e03670f_-menuitem-_root_menu',
            'context-searchselect',
            'context-keywordfield'
        ]
    };

    // Проверяем, не запущен ли скрипт ранее
    if (window[SETTINGS.initializedFlag]) return;
    window[SETTINGS.initializedFlag] = true;

    try {
        // ██████████████████████████████████████████████████████████████
        // █ 1. ДОБАВЛЯЕМ СТИЛИ ДЛЯ СКРЫТИЯ ЛИШНИХ ЭЛЕМЕНТОВ И НАСТРОЙКИ МЕНЮ
        // ██████████████████████████████████████████████████████████████
        const style = document.createElement('style');
        style.id = SETTINGS.styleId;
        style.textContent = `
            #${SETTINGS.menuId} {
                padding-left: 30px;
                display: grid;
                grid-template-columns: repeat(auto-fill, 32px);
                grid-auto-rows: 26px;
                gap: 2px;
            }
            #${SETTINGS.menuId} > menuitem {
                -moz-box-pack: center;
                list-style-image: var(--image) !important;
            }
            ${SETTINGS.hiddenItems.map(id => `#${id}`).join(', ')},
            #${SETTINGS.menuId}:empty {
                display: none !important;
            }
        `;
        document.head.appendChild(style);

        // ██████████████████████████████████████████████████████████████
        // █ 2. СОЗДАЕМ КОНТЕЙНЕР ДЛЯ ИКОНОК
        // ██████████████████████████████████████████████████████████████
        const menugroup = document.createXULElement('menugroup');
        menugroup.id = SETTINGS.menuId;
        
        // Размещаем после поисковой строки или в начало меню
        const searchSelect = document.getElementById('context-searchselect');
        if (searchSelect) {
            searchSelect.after(menugroup);
        } else {
            document.getElementById('contentAreaContextMenu').prepend(menugroup);
        }

        // ██████████████████████████████████████████████████████████████
        // █ 3. ФУНКЦИЯ ФИЛЬТРАЦИИ: ОПРЕДЕЛЯЕМ, КАКИЕ ЭЛЕМЕНТЫ ОСТАВИТЬ
        // ██████████████████████████████████████████████████████████████
        const shouldKeepItem = (item) => {
            const forbiddenClasses = ['menuitem-iconic-webext', 'extension-menu-item'];
            const forbiddenIds = ['ublock', 'adguard', 'grammarly', 'ext-', 'extension-', ...SETTINGS.hiddenItems];
            
            return (
                item.tagName === 'menuitem' &&
                !item.hidden &&
                item.getAttribute('image') &&
                item.getAttribute('label') &&
                !item.id?.includes('_separator') &&
                !forbiddenClasses.some(c => item.classList.contains(c)) &&
                !forbiddenIds.some(id => item.id?.includes(id))
            );
        };

        // ██████████████████████████████████████████████████████████████
        // █ 4. ОБНОВЛЕНИЕ МЕНЮ: УДАЛЯЕМ СТАРЫЕ ЭЛЕМЕНТЫ И ДОБАВЛЯЕМ НОВЫЕ
        // ██████████████████████████████████████████████████████████████
        const refreshMenu = () => {
            // Полностью очищаем меню перед обновлением
            while (menugroup.firstChild) {
                menugroup.removeChild(menugroup.firstChild);
            }
            
            // Находим все элементы меню и фильтруем их
            const allMenuItems = Array.from(document.querySelectorAll('#contentAreaContextMenu menuitem'));
            const validItems = allMenuItems.filter(shouldKeepItem);
            
            // Клонируем и добавляем только нужные элементы
            validItems.forEach(item => {
                const clone = item.cloneNode(true);
                clone.id = ''; // Удаляем ID, чтобы избежать конфликтов
                
                // Назначаем обработчик клика
                clone.addEventListener('command', () => {
                    try {
                        item.click();
                    } catch (e) {
                        console.error('Ошибка при клике:', e);
                    }
                });
                
                menugroup.appendChild(clone);
            });
            
            // Скрываем группу, если нет элементов
            menugroup.hidden = menugroup.children.length === 0;
        };

        // ██████████████████████████████████████████████████████████████
        // █ 5. НАСТРОЙКА СОБЫТИЙ: ОБНОВЛЯЕМ МЕНЮ ПРИ КАЖДОМ ОТКРЫТИИ
        // ██████████████████████████████████████████████████████████████
        const contextMenu = document.getElementById('contentAreaContextMenu');
        contextMenu.addEventListener('popupshowing', refreshMenu);

        // ██████████████████████████████████████████████████████████████
        // █ 6. ОЧИСТКА: УДАЛЯЕМ ЭЛЕМЕНТЫ ПРИ ЗАКРЫТИИ СТРАНИЦЫ
        // ██████████████████████████████████████████████████████████████
        window.addEventListener('unload', () => {
            contextMenu.removeEventListener('popupshowing', refreshMenu);
            document.getElementById(SETTINGS.menuId)?.remove();
            document.getElementById(SETTINGS.styleId)?.remove();
            delete window[SETTINGS.initializedFlag];
        });

    } catch (error) {
        console.error('Ошибка в скрипте контекстного меню:', error);
    }
})();



image.jpg



Кинуть код в поле «Инициализация».
Иконки поисковых систем автоматически подгружаются в контекстное меню из установленного дополнения ContextSearch-web-ext.

Отредактировано leex (Сегодня 08:22:32)

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]