Реализация Context Menu (контекстное меню) в браузерном расширении

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация Context Menu (контекстное меню) в браузерном расширении
Простая
~1 рабочий день
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация Context Menu (контекстное меню) в браузерном расширении

Контекстное меню браузера — быстрый способ дать пользователю действие прямо на выделенном тексте, ссылке или изображении без открытия popup. API простое, но есть несколько нюансов с жизненным циклом и вложенностью.

Разрешение в манифесте

{
  "permissions": ["contextMenus"]
}

Без этого разрешения вызовы chrome.contextMenus молча игнорируются.

Создание пунктов меню

Пункты меню создаются в service worker при установке расширения. Если создавать их при каждом старте SW — получите дубликаты, потому что браузер не очищает их автоматически:

chrome.runtime.onInstalled.addListener(() => {
  // Чистим старые пункты перед созданием новых
  chrome.contextMenus.removeAll(() => {
    chrome.contextMenus.create({
      id: 'translate-selection',
      title: 'Перевести "%s"',
      contexts: ['selection'],
    });

    chrome.contextMenus.create({
      id: 'save-link',
      title: 'Сохранить ссылку в список',
      contexts: ['link'],
    });

    chrome.contextMenus.create({
      id: 'search-image',
      title: 'Поиск по изображению',
      contexts: ['image'],
    });

    // Разделитель
    chrome.contextMenus.create({
      id: 'separator-1',
      type: 'separator',
      contexts: ['selection'],
    });

    chrome.contextMenus.create({
      id: 'copy-clean',
      title: 'Копировать без форматирования',
      contexts: ['selection'],
    });
  });
});

%s в поле title заменяется на выделенный текст (до ~25 символов, браузер обрезает сам).

Типы контекстов

Контекст Срабатывает
selection есть выделенный текст
link правый клик по ссылке
image правый клик по изображению
video / audio медиа-элементы
editable поля ввода, textarea
page любое место на странице
all везде

Обработка кликов

chrome.contextMenus.onClicked.addListener(async (info, tab) => {
  switch (info.menuItemId) {
    case 'translate-selection':
      await handleTranslate(info.selectionText, tab);
      break;

    case 'save-link':
      await handleSaveLink(info.linkUrl, info.pageUrl, tab);
      break;

    case 'search-image':
      await handleImageSearch(info.srcUrl, tab);
      break;

    case 'copy-clean':
      // Выполняем код в контексте страницы
      await chrome.scripting.executeScript({
        target: { tabId: tab.id },
        func: (text) => navigator.clipboard.writeText(text),
        args: [info.selectionText]
      });
      break;
  }
});

async function handleTranslate(text, tab) {
  const { targetLang = 'ru' } = await chrome.storage.sync.get('targetLang');

  const response = await fetch(
    `https://api.mymemory.translated.net/get?q=${encodeURIComponent(text)}&langpair=auto|${targetLang}`
  );
  const data = await response.json();

  // Показываем результат в content script
  await chrome.tabs.sendMessage(tab.id, {
    type: 'SHOW_TRANSLATION',
    original: text,
    translated: data.responseData.translatedText
  });
}

Вложенные меню

chrome.contextMenus.create({
  id: 'parent-send-to',
  title: 'Отправить в...',
  contexts: ['selection', 'link'],
});

chrome.contextMenus.create({
  id: 'send-to-telegram',
  parentId: 'parent-send-to',
  title: 'Telegram',
  contexts: ['selection', 'link'],
});

chrome.contextMenus.create({
  id: 'send-to-notion',
  parentId: 'parent-send-to',
  title: 'Notion',
  contexts: ['selection', 'link'],
});

Динамическое обновление пунктов

Пункт меню можно обновить без пересоздания — удобно для отображения текущего состояния:

async function updateMenuItemState() {
  const { enabled } = await chrome.storage.sync.get('enabled');

  chrome.contextMenus.update('toggle-feature', {
    title: enabled ? 'Отключить подсветку' : 'Включить подсветку',
    checked: enabled // для type: 'checkbox'
  });
}

// Вызываем при изменении настроек
chrome.storage.onChanged.addListener((changes) => {
  if ('enabled' in changes) updateMenuItemState();
});

Меню для конкретных сайтов

documentUrlPatterns ограничивает пункт определёнными URL:

chrome.contextMenus.create({
  id: 'github-open-pr',
  title: 'Открыть PR в новой вкладке',
  contexts: ['link'],
  documentUrlPatterns: ['https://github.com/*'],
  targetUrlPatterns: ['https://github.com/*/pull/*']
});

Контекстное меню — минимально инвазивный UX: пользователь вызывает действие сам, расширение не навязывается.