Вас когда-нибудь раздражало, когда вы копируете ссылку с сайта только для того, чтобы она выплевывает какую-то безбожную кашу, когда вы пытаетесь поделиться ею с друзьями?…..Нет?….Только я? В духе сверхинженеров во всем мире я провел неделю, пытаясь преодолеть серьезные препятствия и обойти серьезные проблемы безопасности, чтобы в конечном итоге решить небольшую проблему, которая, вероятно, не была очень важной.

С недавним свободным временем, предоставленным мне, поскольку я ищу новую должность, я решил поработать над проектом кодирования или двумя на стороне, чтобы создать что-то осязаемое, что я мог бы использовать, а также дать мне повод углубить мою сеть. навыки разработки и JavaScript (это также дало мне повод лучше ознакомиться со стилем Manifest V3).

Результатом стало fURL, расширение браузера для Chrome и Firefox, которое отслеживает, копируете ли вы какие-либо ссылки, а затем удаляет все ненужные параметры UTM или fbclid, чтобы ссылка выглядела чище. По сравнению с сокращателем ссылок, это также имеет дополнительное преимущество, заключающееся в сохранении предварительного просмотра контента, чтобы не было похоже, что вы отправляете что-то хитрое.

От:

https://www.theonion.com/san-francisco-realtor-shows-couple-earning-under-6-figu-1850289467?utm_campaign=The%20Onion&utm_content=1681314305&utm_medium=SocialMarketing&utm_source=facebook&fbclid=IwAR2n9xqcUQIR4rU74QP 10jJIQgqOXFVoJIYExDLAt2Avizj1-5xIAwxbt-s

(блин)

To:

https://www.theonion.com/san-francisco-realtor-shows-couple-earning-under-6-figu-1850289467

(гораздо лучше)

Тем не менее, расширения браузера и веб-страницы могут стать немного раздражающими, когда вы хотите получить доступ к буферу обмена, а тем более к адресной строке, и на это есть веские причины. Если расширение браузера может получить доступ к скопированному паролю, который пользователь использовал и сохранил без явного разрешения, это может быть серьезной угрозой безопасности (Примечание: fURL никогда не будет собирать или сохранять какие-либо данные, а удаляет только несущественные элементы). URL).

Я собираюсь рассказать о процессе разработки и проектирования, а также о проблемах/препятствиях, с которыми я столкнулся на этом пути.

Что плохого в UTM-параметрах?

На самом деле ничего! Они просто не очень важны для вас, пользователя.

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

Удаление параметров UTM может фактически действовать как форма очистки данных, если вы хотите поделиться URL-адресом в другом месте. Если вы копируете ссылку из своей адресной строки, в которой есть параметры UTM, и делитесь ею с кем-то еще, особенно на другой платформе или в другом приложении, то вы фактически передаете искаженное представление о том, откуда исходит контент. Если пользователь открывает ссылку электронной почты с параметрами UTM из Facebook (или fbclid, другой тип тега контента), то система помечает это как успешное попадание из кампании Facebook, даже если пользователь не видел там контент. По этой причине современные статьи по веб-разработке на самом деле не рекомендуют оставлять параметры UTM в URL-адресах после того, как они были успешно зарегистрированы. Таким образом, это расширение помогает сделать вещи чище для пользователей, в первую очередь не затрагивая первоначальную цель UTM.

Философия дизайна:

При разработке своего расширения для браузера я хотел, чтобы оно было максимально ненавязчивым.В идеале, это расширение должно работать в фоновом режиме и использоваться только для проверки того, есть ли у скопированных ссылок параметр UTM. которые мы можем удалить без дополнительных действий со стороны пользователя. По этой причине при создании fURL я отдал приоритет следующим дизайнерским решениям:

  1. Ненавязчивый
  2. Простой
  3. Легкий

Препятствие 1: API navigator.clipboard и document.execCommand(‘copy’)

Первым серьезным препятствием для этого проекта было выяснить, как лучше всего получить доступ к буферу обмена. Недавняя документация предлагает недавно реализованный API navigator.clipboard, который позволяет вам читать и записывать данные прямо из буфера обмена.

Однако на практике использование navigator.clipboard оказалось сложной задачей. В частности, navigator.clipboard требует, чтобы документ оставался в фокусе, что часто приводило людей в беду.

Учитывая, что мое расширение использовало действие всплывающего окна, проблема возникла быстро. Щелкнув по всплывающему окну, я сместил фокус с документа, что привело к вышеупомянутому исключению DOMException.

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

Если бы я хотел использовать navigator.clipboard.readText() для получения скопированного URL-адреса, нуждающегося в форматировании, пользователь должен был бы давать явное разрешение расширению браузера каждый раз, когда он копирует что-либо на новый сайт. Это было бы большой проблемой для пользователя и противоречило бы моему принципу «Ненавязчивый» , поэтому я решил изучить другой подход.

В отличие от этого, document.execCommand не требует тех же разрешений буфера обмена от сайтов браузера, поскольку вместо этого функционально служит нажатию клавиш ctrl+c/ctrl+v. Кроме того, существуют существующие обходные пути, которые позволяют вставлять выборки в элемент документа перед копированием, обходя проблемы с фокусом и разрешениями для navigator.clipboard. Хотя document.execCommand в настоящее время устарел, эта функциональность была проще из двух вариантов и работала значительно лучше.

Код обходного пути:

    let copyFrom = document.createElement('input');
    copyFrom.value = {some_value};

    document.body.appendChild(copyFrom);
    copyFrom.select()
    document.execCommand('copy');
    copyFrom.blur();
    document.body.removeChild(copyFrom);

Препятствие 2: копирование и вставка прослушивателей событий

Как только я решил, как получить доступ к буферу обмена, следующим вопросом, который мне нужно было решить, было когда. Прослушиватели событий позволяют обнаруживать действия, предпринятые в окне (например, копировать, вставить, навести курсор мыши и т. д.), и кажется лучшим подходом, но когда лучше всего его вызывать? Не лучше ли посмотреть на текст, когда он копируется, а затем изменить его перед добавлением в буфер обмена? Или было бы лучше подождать, пока мы не вставим из нашего буфера обмена, а затем изменить результат, прежде чем доставлять его? Оба пришли со своими плюсами и минусами.

Копировать:

Плюсы:

  • Захватив текст при первом копировании, ссылки будут изменены до того, как попадут в буфер обмена, а это означает, что мы можем вставлять их в браузеры/приложения, не беспокоясь впоследствии о сценарии контента.

Минусы:

Вставить:

Плюсы:

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

Минусы:

  • Поскольку мы полагаемся на скрипт содержимого для изменения нашего URL-адреса при вставке, эта функция не будет работать, если мы хотим вставить за пределами нашего браузера/между браузерами.
  • Во время тестирования QA была обнаружена серьезная проблема при попытке вставки в чат FB и тело темы Gmail. Примечательно, что некоторые сайты имеют свои собственные обработчики событий вставки, поэтому попытка перезаписать функцию вставки будет просто добавлена ​​к неизмененному URL-адресу.

Как видите, у нас здесь есть несколько немаловажных блокпостов. Мне пришла в голову идея включить слушателей в события «копирование» и «вставка», чтобы попытаться покрыть все слепые зоны, но был один барьер, который в конечном итоге был слишком сложным, чтобы его обойти.

Поскольку такие сайты, как FB и Gmail, имеют свои собственные обработчики событий вставки, которые нелегко обнаружить, мой код не сможет узнать, когда он должен срабатывать при событии вставки или нет. Я мог бы исключить эти сайты специально из своего манифеста, используя шаблоны соответствия, но это потребовало бы ведения постоянно расширяющегося списка сайтов, занесенных в черный список, что я не был в настроении делать. Вместо этого я решил продолжить использование события копировать и посмотреть, смогу ли я обойти ограничения, с которыми столкнулся.

Препятствие 3: копирование вариантов использования

Теперь, когда я решил изменить текст события «копировать», мне нужно было определить свои варианты использования и как лучше всего решить их проблемы.

  1. Пользователь копирует страницу, используя Ctrl+C или щелчок правой кнопкой мыши + выбор «Копировать»: это может быть обработано прослушивателем события «копировать», описанным выше.
  2. Пользователь копирует из адресной строки: хотя мы не можем использовать прослушиватели событий, чтобы определить, когда URL-адрес копирует адресную строку, мы можем получить доступ к href окна.
  3. Пользователь выбирает «Копировать адрес ссылки» в контекстном меню: хотя мы не можем обнаружить событие «копирования» из «Копировать адрес ссылки», мы можем сказать, когда пользователь щелкнул правой кнопкой мыши на веб-странице.
  4. Пользователь копирует что-то из-за пределов браузера. Учитывая, что мы не можем обнаружить что-то вне браузера, я в конечном итоге решил, что этот вариант использования выходит за рамки.

Препятствие 3.1: Копировать адресную строку

Чтобы преодолеть препятствие, связанное с невозможностью определить, когда адресная строка копируется, я решил, что лучшим подходом будет использование кнопки расширения, чтобы скопировать и обрезать ее напрямую, поскольку мы можем просто сохранить window.href вкладки, которую мы в и скопируйте это. Хотя это добавляет отдельное преднамеренное действие к обычному поведению пользователя, оно существенно уменьшает общее количество действий с 3 до 1 (двойной щелчок по адресной строке (x2) + копирование (x1) вместо нажатия кнопки расширения (x1)). соответствует моему принципу простота.

Препятствие 3.2: Копировать адрес ссылки

Этот был немного сложнее. Поскольку мы могли определить, когда пользователь щелкнул правой кнопкой мыши, но в конечном итоге не могли сказать, выбирает ли пользователь «Копировать адрес ссылки» или думает, я решил больше подумать о том, когда кто-то может щелкнуть правой кнопкой мыши ссылку (что также известно как как открытие контекстного меню).

По моему опыту, я обычно щелкаю правой кнопкой мыши по ссылкам по двум причинам. Либо я пытаюсь открыть ссылку в новом окне, либо пытаюсь скопировать ссылку. В других случаях, когда я обычно могу щелкнуть правой кнопкой мыши (например, чтобы найти слово/фразу в Google или сохранить изображение), вряд ли это произойдет по самой ссылке. Имея это в виду, нам просто нужно найти способ различать, когда пользователь может щелкнуть ссылку, чтобы открыть ее в новой вкладке/окне, и когда он пытается скопировать встроенную гиперссылку.

Поскольку «Открыть ссылку в новой вкладке» и «Открыть ссылку в новом окне», вероятно, будут выбраны быстрее, чем «Копировать адрес ссылки» (учитывая, что они более доступны для выбора курсором), мы можем предположить, что пользователь выберет их, прежде чем они могут выбрать «Копировать адрес ссылки». Кроме того, как только пользователь выбирает «Копировать адрес ссылки», ему обычно требуется дополнительная секунда или две, чтобы навести указатель мыши на существующую вкладку или открыть новое окно и перейти на свой сайт, которым они хотят поделиться.

Принимая все это во внимание (и рассчитывая свои собственные действия), я подсчитал, что большинству людей потребуется около 3 секунд от открытия контекстного меню до выбора «Копировать адрес ссылки», а затем еще одна или две секунды, чтобы перейти к страница, которую они ищут. Для сравнения, открытие новой вкладки/окна обычно занимает менее 2 секунд. Используя эту информацию, я могу сделать вывод, что если пользователь все еще находится на той же странице через 3 секунды после того, как он щелкнул ссылку правой кнопкой мыши, то, скорее всего, он пытается скопировать адрес ссылки. Однако, если мы перешли на новую вкладку или окно, фокус больше не будет находиться на исходном документе. Имея это в виду, мы можем установить тайм-аут, чтобы через 3 секунды проверять, находится ли документ в фокусе. Если это так, то мы можем обрезать URL-адрес в выбранной нами ссылке и передать его напрямую в наш буфер обмена.

setTimeout(function () {
      if (document.hasFocus()) {
//        copy to clipboard
          copyURL(currNode.href);
      } else {
          console.log("document not in focus");
          return;
      }
  }, 3000);

Чтобы определить, выбрали ли мы ссылку или нет, мы берем выделение над нашим местоположением мыши при щелчке правой кнопкой мыши и выбираем ближайший диапазон слова. После этого мы итеративно перемещаемся вверх по parentNodes, пока не наткнемся на тег привязки. Это поможет нам поймать ссылки, которые находятся в блоках текста или расположены вне тегов span.

//Select word where mouse is
const selection = window.getSelection();
selection.removeAllRanges();
const range = document.caretRangeFromPoint(event.clientX, event.clientY);
range.expand('word');
selection.addRange(range);

//check if we can find an anchor node among parentNodes (indicating that the selection is a hyperlink)
let currNode = selection.anchorNode.parentNode
while (currNode) {
    if (currNode.href) {
//      check if user has navigated to a new page within the 3 seconds (indicating "Open in..." has been selected)

//      add setTimeout code here

        break;
    } else {
        currNode = currNode.parentNode;
    }
}

Полученные результаты

И вот оно! Объединив все эти решения, вы получите fURL, легкое и простое в использовании расширение для браузера, которое будет искать копируемые URL-адреса (либо из адресной строки, события копирования Ctrl+C, либо с задержкой по времени при щелчке правой кнопкой мыши/контекстном меню). и украсьте его для совместного использования. Спасибо за чтение, надеюсь, вы нашли это полезным!

Репозиторий: https://github.com/maxmir20/MMMT/tree/main/fURL

Возможные будущие улучшения

  • Добавить модули: учитывая тот факт, что всплывающее окно и сценарий содержимого выполняют почти идентичные действия (сценарий содержимого инициирует прослушиватели событий, которые копируют/обрезают URL-адрес, а сценарий всплывающего окна просто копирует/обрезает URL-адрес). , было бы лучше найти способ повторно использовать одну и ту же функцию. Для этого следующим шагом будет реализация модуля/ресурса, доступного через Интернет.
  • Добавить параметры: я хотел бы предоставить пользователю больше контроля над возможностью включать/отключать fURL или даже получать доступ к предыдущим значениям буфера обмена, если что-то было скопировано по ошибке.
  • Улучшение ссылок перенаправления. Если вы когда-либо пытались скопировать ссылку со своей стены Facebook, вы могли заметить, что вокруг нее появляется уродливая обертка. Я хотел бы добавить дополнительную обрезку формата для этих типов URL-адресов, чтобы извлечь исходный URL-адрес перед удалением параметров UTM.