За последние 24 часа нас посетили 108795 программистов и 5619 роботов. Сейчас ищут 2614 программистов ...

Виджет обратного звонка

Тема в разделе "PHP Free-Lance", создана пользователем Seotime, 12 мар 2026.

  1. Seotime

    Seotime Активный пользователь

    С нами с:
    12 май 2021
    Сообщения:
    13
    Симпатии:
    0
    Задача такая: есть готовый виджет обратного звонка (набор html, php, css, js) необходимо это скомпоновать (я думаю завернуть в бандл) с целью установки на другие ресурсы (сторонние домены). Идея такая - размещаем виджет обратного звонка (допустим скрипт) единоразово. Если необходимо редактировать - это делается в одном месте, все остальные сайты "транслируют" уже отредактированный код. Либо JS скриптом вставляется (это пример как у других реализовано, здесь куча параметров собирается, которые не нужны).

    Код (Text):
    1. <script>
    2. (function(w,d,n,c){w.CallDataObject=n;w[n]=function(){w[n]["callbacks"].push(arguments)};if(!w[n]["callbacks"]){w[n]["callbacks"]=[]}w[n]["loaded"]=false;if(typeof c!=="object"){c=[c]}w[n]["counters"]=c;for(var i=0;i<c.length;i+=1){p(c[i])}function p(cId){var a=d.getElementsByTagName("script")[0],s=d.createElement("script"),i=function(){a.parentNode.insertBefore(s,a)},m=typeof Array.prototype.find === 'function',n=m?"init-min.js":"init.js";s.async=true;s.src="https://mod.calltouch.ru/"+n+"?id="+cId;if(w.opera=="[object Opera]"){d.addEventListener("DOMContentLoaded",i,false)}else{i()}}})(window,document,"ct","123879457");
    3. </script>

    Сколько по времени и по деньгам?
     
  2. jei

    jei Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    542
    Симпатии:
    0
    зачем тебе этот скрипт?
     
  3. don.bidon

    don.bidon Активный пользователь

    С нами с:
    28 мар 2021
    Сообщения:
    945
    Симпатии:
    146
    Рекомендую освоить composer (который писан на PHP, но умеет работать с файлами любого типа).
     
  4. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.833
    Симпатии:
    1.335
    Адрес:
    Лень
    1. Центральный сервер (PHP)
    Файл: widget-api.php Этот файл генерирует данные и, самое главное, убивает кэш.
    PHP:
    1. <?php
    2. // widget-api.php
    3.  
    4. // 1. ЗАГОЛОВКИ ДЛЯ ОТКЛЮЧЕНИЯ КЭША (Космически важно!)))
    5. header("Content-Type: application/json; charset=utf-8");
    6. header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
    7. header("Cache-Control: post-check=0, pre-check=0, false");
    8. header("Pragma: no-cache");
    9. header("Expires: 0");
    10.  
    11. // 2. ГЕНЕРАЦИЯ ДАННЫХ (Имитация базы данных)
    12. $config = [
    13.     "version" => time(), // Уникальная версия (timestamp) для обхода кэша файлов
    14.     "widget" => [
    15.         "type" => "loader",
    16.         "text" => "Загрузка данных...",
    17.         "color" => "#3498db",
    18.         "size" => "50px",
    19.         // Можно передавать HTML шаблон или просто данные для рендера
    20.         "template_id" => "spinner-v1"
    21.     ]
    22. ];
    23.  
    24. echo json_encode($config);
    2. Библиотека виджета (JS + CSS)
    Файл: widget-core.js Это "тяжелая" часть, которая содержит стили и логику. Она загружается только после получения конфига.
    PHP:
    1. // widget-core.js
    2.  
    3. (function() {
    4.     // CSS стили виджета (инжектим их прямо в JS, чтобы не грузить отдельный файл CSS)
    5.     const styles = `
    6.         .central-widget-container {
    7.             position: fixed;
    8.             top: 0; left: 0; width: 100%; height: 100%;
    9.             background: rgba(255,255,255,0.9);
    10.             display: flex;
    11.             flex-direction: column;
    12.             justify-content: center;
    13.             align-items: center;
    14.             z-index: 9999;
    15.             font-family: sans-serif;
    16.             transition: opacity 0.5s ease;
    17.         }
    18.         .spinner {
    19.             border: 5px solid #f3f3f3;
    20.            border-top: 5px solid var(--widget-color);
    21.             border-radius: 50%;
    22.             width: var(--widget-size);
    23.             height: var(--widget-size);
    24.             animation: spin 1s linear infinite;
    25.             margin-bottom: 15px;
    26.         }
    27.         .widget-text {
    28.             color: #333;
    29.            font-weight: bold;
    30.         }
    31.         @keyframes spin {
    32.             0% { transform: rotate(0deg); }
    33.             100% { transform: rotate(360deg); }
    34.         }
    35.     `;
    36.  
    37.     // Функция инициализации виджета
    38.     window.initCentralWidget = function(config) {
    39.         const data = config.widget;
    40.      
    41.         // 1. Создаем стили
    42.         const styleSheet = document.createElement("style");
    43.         styleSheet.innerText = styles;
    44.         document.head.appendChild(styleSheet);
    45.  
    46.         // 2. Создаем HTML
    47.         const container = document.createElement("div");
    48.         container.className = "central-widget-container";
    49.         container.style.setProperty('--widget-color', data.color);
    50.         container.style.setProperty('--widget-size', data.size);
    51.      
    52.         container.innerHTML = `
    53.             <div class="spinner"></div>
    54.             <div class="widget-text">${data.text}</div>
    55.         `;
    56.  
    57.         document.body.appendChild(container);
    58.  
    59.         // 3. Пример логики: скрыть виджет через 3 секунды (имитация загрузки)
    60.         setTimeout(() => {
    61.             container.style.opacity = '0';
    62.             setTimeout(() => container.remove(), 500);
    63.         }, 3000);
    64.      
    65.         console.log("Widget loaded with version:", config.version);
    66.     };
    67. })();
    3. Загрузчик (Loader)
    Файл: loader.js Этот скрипт размещается на сайтах клиентов. Он делает запрос к PHP, получает версию и динамически подключает widget-core.js.

    PHP:
    1. // loader.js
    2.  
    3. (function() {
    4.     // URL центрального сервера
    5.     const API_URL = 'https://your-central-site.com/widget-api.php';
    6.     // Путь к самому виджету (на том же сервере)
    7.     const WIDGET_LIB_URL = 'https://your-central-site.com/widget-core.js';
    8.  
    9.     // Функция загрузки скрипта
    10.     function loadScript(src, callback) {
    11.         const script = document.createElement('script');
    12.         script.src = src;
    13.         script.async = true;
    14.         script.onload = callback;
    15.         document.head.appendChild(script);
    16.     }
    17.  
    18.     // 1. Делаем запрос к API за конфигом
    19.     // Добавляем random, чтобы сам этот запрос тоже не закэшировался браузером агрессивно
    20.     fetch(API_URL + '?t=' + new Date().getTime())
    21.         .then(response => response.json())
    22.         .then(data => {
    23.             // 2. Получаем версию из JSON
    24.             const version = data.version;
    25.          
    26.             // 3. Формируем URL библиотеки с параметром версии (Cache Busting)
    27.             // Браузер увидит новый URL и скачает файл заново
    28.             const libUrlWithVersion = `${WIDGET_LIB_URL}?v=${version}`;
    29.  
    30.             // 4. Загружаем библиотеку виджета
    31.             loadScript(libUrlWithVersion, () => {
    32.                 // 5. Когда библиотека загрузилась, запускаем её с данными
    33.                 if (typeof window.initCentralWidget === 'function') {
    34.                     window.initCentralWidget(data);
    35.                 }
    36.             });
    37.         })
    38.         .catch(err => console.error("Widget load error:", err));
    39. })();
    4. Пример использования на клиентском сайте

    PHP:
    1. <!DOCTYPE html>
    2. <html lang="ru">
    3. <head>
    4.     <meta charset="UTF-8">
    5.     <title>Сайт клиента с виджетом</title>
    6. </head>
    7. <body>
    8.  
    9.     <h1>Контент сайта клиента</h1>
    10.     <p>Здесь виджет должен появиться поверх всего.</p>
    11.  
    12.     <!-- Подключение загрузчика виджета -->
    13.     <!-- defer гарантирует, что скрипт выполнится после парсинга HTML -->
    14.     <script src="https://your-central-site.com/loader.js" defer></script>
    15.  
    16. </body>
    17. </html>
    Как это решает проблему кэша?
    1. API (widget-api.php): Заголовки Cache-Control: no-store гарантируют, что браузер каждый раз пойдет на сервер за JSON-файлом, а не возьмет его из памяти.
    2. Версионирование файлов: В JSON возвращается version (timestamp). Загрузчик берет этот timestamp и добавляет его к URL загрузки JS-библиотеки: widget-core.js?v=171562345.
      • Если вы изменили код виджета и обновили timestamp в PHP, URL изменится.
      • Браузер увидит новый URL и скачает новый JS файл, игнорируя старый кэш.
    3. Ленивая загрузка: Скрипт loader.js выполняется асинхронно и не блокирует отображение основного контента сайта клиента.

    Как обновить виджет?
    Вам нужно просто изменить файл widget-core.js или widget-api.php на центральном сервере.
    • Если меняете логику/стили: обновляете widget-core.js.
    • Если меняете текст/цвет: обновляете массив $config в widget-api.php.
    • Важно: Убедитесь, что в $config поле "version" меняется (например, time() делает это автоматически каждую секунду).


    15 минут заняло