Пишем расширение для браузера Chrome для поиска по истории посещенных страниц

0

Пишем расширение для браузера Chrome для поиска по истории посещенных страниц

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

Файловая структура проекта:


Data:.
│   history.html
│   manifest.json

├───images
│       ic_history.png

├───popup
│       popup.html
│       popup.js

└───scrips
        history.js


Для начала рассмотрим файл manifest.json:


{
    "manifest_version": 3,
    "name": "My history",
    "description": "Featured Chrome history",
    "version": "1.0",
    "action": {
      "default_popup": "popup/popup.html",
      "default_icon": "images/ic_history.png"
    },
    "permissions": [
      "history",
      "tabs",
      "activeTab"
    ]
  }


Файл popup/popup.html — отображает кнопку для открытия страницы расширения:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello</title>
</head>
<body>
    <div id="extension">
        <button id="openHistoryBtn">Open history</button>
    </div>
    <script src="popup.js"></script>
</body>
</html>


Файл popup/popup.js — при нажатии на кнопку в браузере откроется новое окно, которое отобразит функционал поиска по истории.

const openHistoryBtn = document.getElementById('openHistoryBtn');
openHistoryBtn.addEventListener('click', (e) => {

    chrome.tabs.create({ url: 'history.html' });
});

Теперь рассмотрим сам файл history.html, где как раз и располагается вся основная разметка приложения.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>History</title>

    <style>
        * {
            box-sizing: border-box;
        }

        body {
            font-size: 1rem;
        }

        .container {
            max-width: 1368px;
            margin: 0 auto;
            padding: 0 8px;
        }

        .row {
            display: flex;
            gap: 10px;
            margin-top: 20px;
        }

        .md:w-100 {
            width: 10%;
        }

        button {
            padding: 8px 16px;
            border: 1px solid rgb(12, 113, 245);
            border-radius: 5px;
            cursor: pointer;
        }

        .form-input {
            width: 100%;
            margin-bottom: 8px;
        }

        .form-input>* {
            display: block;
        }

        .form-input>label {
            cursor: pointer;
            margin-bottom: 8px;
        }

        input {
            width: 100%;
            padding: 8px;
            border: 1px solid rgb(12, 113, 245);
            border-radius: 5px;
        }

        input:focus {
            outline: 1px solid rgb(251, 202, 5);
        }

        table,
        th,
        td {
            border: 1px solid black;
            border-collapse: collapse;
        }

        table {
            overflow-wrap: break-word;
            table-layout: fixed;
            width: 100%;
            border: 1px solid rgb(8, 130, 237);
            text-align: center;
            margin-top: 20px;
        }

        table>tr {
            padding: 8px;
        }

        table td,
        table th {
            padding: 8px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="container">
            <h2>Chrome history search</h2>

            <form>
                <div class="form-input">
                    <label for="searchTermText">Search in title</label>
                    <input type="text" id="searchTermText" required />
                </div>

                <div class="row">

                    <div class="form-input">
                        <label for="searchResultsMaxCount">Search results max count</label>
                        <input type="number" id="searchResultsMaxCount" value="100" required />
                    </div>

                    <div class="form-input">
                        <label for="startTimeDateTimePicker">Start date</label>
                        <input type="date" id="startTimeDateTimePicker" style="font-size: 0.74rem" required />
                    </div>
                </div>

                <div class="row">
                    <button class="button" id="startSearchButton">Search</button>
                </div>
            </form>

            <table class="table">

                <thead>
                    <tr>
                        <th>Id</th>
                        <th>Last visist time</th>
                        <th>title</th>
                        <th>Typed count</th>
                        <th>Url</th>
                        <th>Visit count</th>
                    </tr>
                </thead>

                <tbody id="searchResults"></tbody>

            </table>

        </div>
    </div>
    <script src="scrips/history.js"></script>
</body>

</html>

А теперь рассмотрим файл scripts/history.js:

const app = document.getElementById('app');
const searchResults = document.getElementById('searchResults');
const startSearchButton = document.getElementById('startSearchButton');

function convert_days_to_timestamp(days) {
    const microsecondsPerWeek = 1000 * 60 * 60 * 24 * days;
    return (new Date).getTime() - microsecondsPerWeek;
}

function datetime_format(timestamp) {

    if (!timestamp) return '';
    let dt_formatted = '';

    const dtFormat = new Intl.DateTimeFormat("ru", {
        weekday: "short",
        year: "numeric",
        month: "long",
        day: "numeric",
        hour: "numeric",
        minute: "numeric"
    });

    try {
        dt_formatted = dtFormat.format(new Date(timestamp));
    }
    catch (e) {
        return '';
    }

    return dt_formatted;
}

function show_history_entries(text, maxResultsCount, startTime) {
    // обращаемся к Chrome Extensions API и получаем необходимые данные
    chrome.history
        .search({
            text: text || 'google',
            maxResults: maxResultsCount || 100000,
            startTime: startTime || new Date('01/01/2022').getTime()
        })
        .then(entries => {

            const rows = entries.map(entry => {

                const values = Object.values(entry).map((value, index) => {
                    let cell = '';

                    switch (index) {
                        case 1:
                            cell = `<td>${datetime_format(value)}</td>`;
                            break;

                        case 4:
                            cell = `<td><a href="${value}">Go</a></td>`;
                            break;

                        default:
                            cell = `<td>${value}</td>`;
                            break;
                    }

                    return cell;
                });

                return `<tr>${values.join('')}</tr>`;
            })

            searchResults.innerHTML = rows.join('');
        });

}

startSearchButton.addEventListener('click', (e) => {

    e.preventDefault();

    const searchTermText = document.getElementById('searchTermText');
    const searchResultsMaxCount = document.getElementById('searchResultsMaxCount');
    const startTimeDateTimePicker = document.getElementById('startTimeDateTimePicker');

    const text = searchTermText.value.trim();
    const maxCount = Number(searchResultsMaxCount.value.trim());
    const startTime = startTimeDateTimePicker.value.trim();

    const daysAgo = Date.now() -  new Date(startTime).getTime();

    console.log(text, maxCount, daysAgo);
    show_history_entries(text, maxCount, daysAgo);

});

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

Вот таким образом мы создали простое расширение для браузера Chrome, которое позволяет вести поиск по истории с дополнительными фильтрами.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.