Javascript-форум (https://javascript.ru/forum/)
-   Javascript под браузер (https://javascript.ru/forum/css-html/)
-   -   Расширение для браузера: выводить на странице информацию о владельце из базы (https://javascript.ru/forum/css-html/76861-rasshirenie-dlya-brauzera-vyvodit-na-stranice-informaciyu-o-vladelce-iz-bazy.html)

trommo 21.02.2019 13:58

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

Например, захожу я на сайт "Одноклассников" или "Мой мир", а в углу всплывает прямоугольник, а в нём логотипчик группы mail.ru и чуть ниже фраза "принадлежит группе mail.ru".

Начал разбираться как это всё организовать на примере простейшего расширения, вот его файл manifest.json:

{

  "manifest_version": 2,
  "name": "Borderify",
  "version": "1.0",

  "description": "Adds a solid red border to all webpages matching mozilla.org.",
  "icons": {
    "48": "icons/border-48.png"
  },

  "applications": {
    "gecko": {
      "id": "borderify@mozilla.org",
      "strict_min_version": "45.0"
    }
  },

  "content_scripts": [
    {
      "matches": ["*://*.mozilla.org/*"],
      "js": ["borderify.js"]
    }
  ]

}


И застрял. Если "в лоб", то получается, что в файле manifest.json нужно указывать все урлы из базы, а к ним соответствующий файл скипта, где будут прописываться стили для каждой группы урлов:

"content_scripts": [
    {
      "matches": ["*://*.mozilla.org/*", "*://*.google.com/*"],
      "js": ["borderify.js"]
    },
    {
      "matches": ["*://*.opera.com/*", "*://*.stackoverflow.com/*"],
      "js": ["borderify_green.js"]
    }
  ]


Здесь файлы скриптов borderify.js and borderify_green.js содержат стили:

document.body.style.border = "5px solid red";

и
document.body.style.border = "5px solid green";


соответственно.

Т.е. на всех страницах первых двух сайтов с их поддоменами будет появляться красная рамочка, а у вторых двух - зелёная.

Однако что-то подсказывает мне, что это неправильно, и всю эту логику нужно выносить в отдельный файл, а не держать её в файле manifest.json. Потому что групп урлов в базе может в итоге оказаться десятки-сотни, и для каждой группы свой стиль.

Тогда получается в файле manifest.json всё красиво и аккуратно:

"content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["borderify.js"]
    }
  ]


Осталось только разобраться, как задавать if-else условия в файле borderify.js.

Кто-нибудь делал что-то подобное? Помогите вынести логику в отдельный файл.

Nexus 21.02.2019 14:20

Цитата:

Сообщение от trommo
Однако что-то подсказывает мне, что это неправильно

Здравый смысл, наверное.

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

Как-то так:
if(location.host==='javascript.ru')
    document.body.style.border='solid 5px #0F0';


Можно еще сделать так:
const controllers={
    'javascript.ru':()=>{
        document.body.style.border='solid 5px #0F0';
    },
    'google.ru':()=>{
        document.body.style.color='#FFF';
    }
};

if(!!controllers[location.host])
    controllers[location.host]();

trommo 21.02.2019 15:29

Цитата:

Сообщение от Nexus (Сообщение 503907)
Здравый смысл, наверное.

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

Как-то так:
if(location.host==='javascript.ru')
    document.body.style.border='solid 5px #0F0';


Можно еще сделать так:
const controllers={
    'javascript.ru':()=>{
        document.body.style.border='solid 5px #0F0';
    },
    'google.ru':()=>{
        document.body.style.color='#FFF';
    }
};

if(!!controllers[location.host])
    controllers[location.host]();

Спасибо, работает!

Однако вопрос с поддоменами остался - нужно явно указывать каждый поддомен сайта в этом списке. Уже с гуглом оказалось, что нужно указывать не просто
'google.ru':()=>{
        document.body.style.border='solid 5px green';
, а
'www.google.ru':()=>{
        document.body.style.border='solid 5px green';

Нет ли возможности указать какое-нибудь выражение как в старт-посте, вроде
*.google.ru
?

В лоб перепробовал и с host, и с hostname - не проходит... Получается, что нужно брать hostname и как-то вытаскивать из него (с помощью регулярных выражений, например) сам домен без поддоменов?

Nexus 21.02.2019 15:37

trommo, можете с помощью регулярок, а можете просто разбить домен на части и смотреть уже по ним.

Например:
const domainParts=location.host.split('.');
const secondLevelDomain=domainParts.slice(-2).join('.');
if(!!controllers[secondLevelDomain])
    controllers[secondLevelDomain]();

trommo 21.02.2019 23:53

Я всё-таки пошел по регуляркам и получилось. Если кому интересно:

const controllers=[
  {
    host: "(.*\.)?google\..*", action:()=>{
        document.body.style.border='solid 5px red';
    } },
  {
    host: "(.*\.)?javascript\.ru", action:()=>{
        document.body.style.border='solid 5px green';
    } },
  {
    host: "(.*\.)?stackoverflow\.com", action:()=>{
        document.body.style.border='solid 5px blue';
    } }
];

for (var i = 0; i < controllers.length; i++)
if (!!location.hostname.match(controllers[i].host)) 
  controllers[i].action();

trommo 25.02.2019 20:23

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

"content_scripts": [
    {
      "matches": ["<all_urls>"],
      "css": ["styles/main.css"],
      "js": ["whoiswhoose.js"]
    }
  ],

  "web_accessible_resources": [
    "photos/*.png",
    "*.png"
  ]


А в файле с логикой whoiswhoose.js пока вручную прописываем каждый контейнер:

const controllers=[
  {
    host: "(.*\.)?google\..*", action:()=>{
        let newDiv = document.createElement('div');
        newDiv.innerHTML += '<p>' + "Сергей Брин" + '</p>';
        newDiv.innerHTML += "<center><img src='https://raw.githubusercontent.com/trommo/whoiswhose/master/brin.png'></center>";
        newDiv.innerHTML += '<p>' + "Основатель Google, совладелец Youtube и прочих сервисов" + '</p>';
        newDiv.classList.add('popup');
        document.body.appendChild(newDiv);
    } },
  {
    host: "(.*\.)?facebook\.com", action:()=>{
        let newDiv = document.createElement('div');
        newDiv.innerHTML += '<p>' + "Марк Цукерберг" + '</p>';
        newDiv.innerHTML += "<center><img src='https://raw.githubusercontent.com/trommo/whoiswhose/master/zuckerberg.png'></center>";
        newDiv.innerHTML += '<p>' + "Основатель Facebook" + '</p>';
        newDiv.classList.add('popup');
        document.body.appendChild(newDiv);
    } },
  {
    host: "(.*\.)?instagram\.com", action:()=>{
        let newDiv = document.createElement('div');
        newDiv.innerHTML += '<p>' + "Марк Цукерберг" + '</p>';
        newDiv.innerHTML += "<center><img src='https://raw.githubusercontent.com/trommo/whoiswhose/master/zuckerberg.png'></center>";
        newDiv.innerHTML += '<p>' + "В 2004 году основал Facebook, с 2012 года совладелец Instagram" + '</p>';
        newDiv.classList.add('popup');
        document.body.appendChild(newDiv);
    } }
];

for (var i = 0; i < controllers.length; i++)
if (!!location.hostname.match(controllers[i].host)) {controllers[i].action(); break;}


Стиль, как видно из манифеста, задаётся в файле styles/main.css:
.popup {
  color: red;
  position: fixed;
  top: 60px;
  left: 20px;
  z-index: 10000;
  width: 140px !important;
  height: 280px;
  opacity: 50%;
  background: black;
  border: 5px solid orange;
}

p {
  text-align: left;
  margin: 5px;
}


Вроде как–то работает, но оставляет множество вопросов:

1) Столкнулся с проблемой, что попап с информацией о владельце вытягивает часть стилей с каждого сайта, на котором он отображается (по логике скрипта). Не то, чтобы это совсем уродливо выглядело, но глаз замечает. Не подскажете, как исправить это, чтобы попап–контейнер с картинкой и текстом смотрелся более–менее одинаково на разных сайтах?

2) Также обнаружилось, что я не могу подгружать картинки из папки с аддоном/расширением. Причем подгружать из интернета с любого стороннего сайта получается, а из папки — нет. Не встречали такое?

3) Как видите, на примере трех доменов, напрашивается вывод, что данные можно хранить в отдельном файле, где будет находиться двухмерный массив:

var content = [
["(.*\.)?google\..*", "Сергей Брин", "./IMG/brin.png", "Описание Брина"],
["(.*\.)?facebook\.com", "Марк Цукерберг", "./IMG/zuckerberg.png", "Описание Цукерберга"],
["(.*\.)?instagram\.com", "Марк Цукерберг", "./IMG/zuckerberg.png", "Описание Цукерберга"]
]


Тогда в скрипте с логикой можно будет оставить только лишь цикл, который будет пробегаться по этому массиву и в случае совпадения текущего домена в открытой вкладке браузера с паттерном из базы, будет подгружать имя владельца сайта, его фото и описание.

Единственный минус в этом деле — проблема со случаем, когда владельцев два и более. Пока не представляю четко, как это можно автоматизировать кодом. Намётки есть, сводящиеся к трёхмерному массиву — но по–моему это уже нездорово и может серьёзно грузить браузер.


Часовой пояс GMT +3, время: 23:20.