New chat
30 Days
Добавление контента в модальное окно
PHP: Разбор строк с префиксами и цифрами
Форма добавления данных с AJAX
Создание базы данных SQLite с PHP
SQLite datetime timezone issue solution
Поиск и сравнение email в PHP
Проверка несоответствий order_id в SQLite3
Удаление случайной части строки в PHP
Получение значения id_corpcom при нажатии
Ошибка OpenSSL: устаревший алгоритм шифрования
2025-04
Добавление виджетов сайтов на Android
Сбор значений класса countch с jQuery
Декодирование текста письма Windows-1251 в PHP
Изменение URL в браузере без перезагрузки
2025-03
1 подключить bootstrap создать ф
2025-02
notes audio move block
php imap
code pj code notes
img docup cdn
fj
mailer
пазлов svg
gif
использовать php bootstrap datat
загрузить html блок с одного адр
dynamic sidebar html css bootstr
используя php bootstrap datatabl
fullcalendar datatable
php прибывать к формату 2025-02-
код js
2025-01
кто я
Get App
My Profile
Удаление случайной части строки в PHP
используя PHP Есть строка src="cid:image003.png@01DBC4D3.B01D85F0" нужно удалить @01DBC4D3.B01D85F0 где 01DBC4D3.B01D85F0 может быть разным рандомным значением Не не изменяются символы в начале @ и в конце " Что бы из строки src="cid:image003.png@01DBC4D3.B01D85F0" получилось src="cid:image003.png"

Вот решение на PHP, которое удаляет часть строки после символа @ до закрывающей кавычки ", оставляя остальное без изменений:

php
Copy
Download
$string = 'src="cid:image003.png@01DBC4D3.B01D85F0"';
$result = preg_replace('/@[^"]+/', '', $string);
echo $result;

Результат:

text
Copy
Download
src="cid:image003.png"

Объяснение:

  • preg_replace выполняет замену по регулярному выражению.

  • Регулярное выражение /@[^"]+/ ищет:

    • @ — символ, после которого нужно удалить текст.

    • [^"]+ — один или более символов, которые не являются кавычкой (").

  • Заменяем найденное совпадение на пустую строку (''), тем самым удаляя ненужную часть.

Этот способ работает для любых случайных значений после @, сохраняя структуру строки до @ и после кавычки.

Используя PHP jquery Если форму вставить динамично из памяти картинку При отправке через POST отправляется изображение <img src="blob:https://example.com/16f4cd3a-157c-4096-92d0-05991caf2bc1" style="width: 300px;" class="fr-fic fr-dib"> Как ее сохранить <img src="blob:https://example.com/16f4cd3a-157c-4096-92d0-05991caf2bc1" style="width: 300px;" class="fr-fic fr-dib">

Если у вас есть изображение в формате blob: (например, загруженное через <input type="file"> и отображенное в <img src="blob:...">), то для его сохранения на сервер нужно:

  1. Получить blob-данные (обычно это File или Blob объект).

  2. Отправить их на сервер с помощью FormData или fetch.

  3. Сохранить на сервере (PHP).


1. Получение и отправка blob-изображения (jQuery + JavaScript)

Допустим, у вас есть <img> с src="blob:...", и вы хотите отправить его на сервер при отправке формы.

Пример кода (jQuery + AJAX):

javascript
Copy
Download
// Предположим, что у вас есть форма с id="myForm"
$('#myForm').on('submit', function(e) {
    e.preventDefault(); // Отменяем стандартную отправку

    // Находим blob-изображение (например, первое в форме)
    const imgElement = $('img[src^="blob:"]')[0];
    
    if (!imgElement) {
        alert('No blob image found!');
        return;
    }

    // Получаем blob-данные из src
    fetch(imgElement.src)
        .then(res => res.blob())
        .then(blob => {
            // Создаем FormData для отправки
            const formData = new FormData();
            formData.append('image', blob, 'uploaded_image.png'); // 'image' - имя поля на сервере

            // Отправляем на сервер
            return fetch('upload.php', {
                method: 'POST',
                body: formData,
            });
        })
        .then(response => response.json())
        .then(data => {
            console.log('Success:', data);
            alert('Image saved!');
        })
        .catch(error => {
            console.error('Error:', error);
            alert('Error uploading image!');
        });
});

2. Сохранение изображения на сервере (PHP)

Создайте файл upload.php, который примет изображение и сохранит его:

php
Copy
Download
<?php
header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['error' => 'Invalid request method']);
    exit;
}

if (!isset($_FILES['image'])) {
    echo json_encode(['error' => 'No image uploaded']);
    exit;
}

$uploadDir = 'uploads/'; // Папка для сохранения
if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0755, true);
}

$file = $_FILES['image'];
$fileName = uniqid() . '.png'; // Генерируем уникальное имя
$filePath = $uploadDir . $fileName;

if (move_uploaded_file($file['tmp_name'], $filePath)) {
    echo json_encode([
        'success' => true,
        'path' => $filePath, // Путь к сохраненному файлу
        'url' => 'https://yourdomain.com/' . $filePath, // Полный URL
    ]);
} else {
    echo json_encode(['error' => 'Failed to save image']);
}
?>

3. Замена blob: на реальный URL после загрузки

После успешной загрузки вы можете заменить src изображения на серверный URL:

javascript
Copy
Download
.then(data => {
    if (data.success) {
        // Заменяем blob: на реальный URL
        $(imgElement).attr('src', data.url);
        alert('Image saved at: ' + data.url);
    }
})

Итог:

  1. Клиентская часть (JS/jQuery):

    • Находит <img src="blob:...">.

    • Конвертирует blob: в FormData.

    • Отправляет на сервер через AJAX.

  2. Серверная часть (PHP):

    • Принимает файл через $_FILES.

    • Сохраняет в папку uploads/.

    • Возвращает URL сохраненного изображения.

  3. После успешной загрузки:

    • Заменяет blob: на реальный URL.

Теперь изображение будет сохранено на сервере, а в HTML останется нормальный путь (/uploads/123abc.png). 🚀

Подробнее расписать Если несколько изображений ?

Если у вас несколько изображений с blob:-URL, и их нужно отправить на сервер, сохранить, а затем заменить src на реальные пути, то процесс немного усложняется.

План действий:

  1. Найти все <img> с src="blob:..." в форме/документе.

  2. Подготовить данные (конвертировать blob: в Blob или File).

  3. Отправить их на сервер (FormData, fetch).

  4. Обработать на сервере (PHP, сохранить каждое изображение).

  5. Обновить src у всех <img> после успешной загрузки.


1. Клиентская часть (JavaScript/jQuery)

Шаг 1: Находим все blob-изображения

javascript
Copy
Download
// Находим все <img>, у которых src начинается с "blob:"
const blobImages = $('img[src^="blob:"]');
if (blobImages.length === 0) {
    console.log('No blob images found');
    return;
}

Шаг 2: Собираем все blob-изображения в FormData

javascript
Copy
Download
const formData = new FormData();

// Добавляем каждое изображение в FormData
blobImages.each(function(index, imgElement) {
    fetch(imgElement.src)
        .then(res => res.blob())
        .then(blob => {
            // Добавляем в FormData с уникальным именем
            formData.append(`images[${index}]`, blob, `image_${index}.png`);
        });
});

Шаг 3: Отправляем на сервер

javascript
Copy
Download
fetch('upload.php', {
    method: 'POST',
    body: formData,
})
.then(response => response.json())
.then(data => {
    if (data.success) {
        // Проходим по всем изображениям и обновляем src
        blobImages.each(function(index, imgElement) {
            if (data.savedPaths[index]) {
                $(imgElement).attr('src', data.savedPaths[index]);
            }
        });
        alert('All images saved!');
    } else {
        console.error('Error:', data.error);
    }
})
.catch(error => {
    console.error('Upload failed:', error);
});

2. Серверная часть (PHP)

Шаг 1: Принимаем несколько файлов

php
Copy
Download
<?php
header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['error' => 'Invalid request method']);
    exit;
}

if (empty($_FILES['images'])) {
    echo json_encode(['error' => 'No images uploaded']);
    exit;
}

$uploadDir = 'uploads/';
if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0755, true);
}

$savedPaths = [];
$errors = [];

foreach ($_FILES['images']['tmp_name'] as $index => $tmpName) {
    if ($_FILES['images']['error'][$index] !== UPLOAD_ERR_OK) {
        $errors[] = "Error uploading image {$index}";
        continue;
    }

    $fileName = uniqid() . '.png'; // или оригинальное имя: $_FILES['images']['name'][$index]
    $filePath = $uploadDir . $fileName;

    if (move_uploaded_file($tmpName, $filePath)) {
        $savedPaths[$index] = $filePath; // или полный URL: 'https://site.com/' . $filePath
    } else {
        $errors[] = "Failed to save image {$index}";
    }
}

if (empty($errors)) {
    echo json_encode([
        'success' => true,
        'savedPaths' => $savedPaths,
    ]);
} else {
    echo json_encode([
        'success' => false,
        'error' => implode(', ', $errors),
    ]);
}
?>

3. Обновление HTML после загрузки

После успешного ответа от сервера (data.savedPaths содержит пути к сохранённым изображениям), мы заменяем blob: на реальные URL:

javascript
Copy
Download
blobImages.each(function(index, imgElement) {
    if (data.savedPaths[index]) {
        $(imgElement).attr('src', data.savedPaths[index]);
    }
});

Итог

  1. Находим все <img src="blob:..."> ($('img[src^="blob:"]')).

  2. Конвертируем blob: в Blob (fetch().then(res => res.blob())).

  3. Отправляем массив файлов (FormData, append('images[]', ...)).

  4. Сервер сохраняет каждое изображение (move_uploaded_file).

  5. Обновляем src у всех <img> после успешной загрузки.

Пример HTML после обработки

До:

html
Copy
Download
Run
<img src="blob:https://example.com/abc123" class="fr-fic">
<img src="blob:https://example.com/def456" class="fr-fic">

После:

html
Copy
Download
Run
<img src="/uploads/65a8d3e1.png" class="fr-fic">
<img src="/uploads/7b2e4f0c.png" class="fr-fic">

Теперь все изображения сохранены на сервере, а в HTML подставлены реальные URL. 🚀

Использую скрипт FroalaEditor для формы вставлю изображения форму не находит blob:https://... изображения при сохранении

Если Froala Editor вставляет изображения в формате blob:, но при отправке формы они не передаются на сервер, значит, нужно:

1. Проверить, что blob:-изображения доступны перед отправкой

Froala Editor хранит загруженные изображения в памяти браузера (blob:), но они не прикрепляются автоматически к форме при отправке.

2. Решение: Извлечь blob:-изображения и отправить их отдельно

Нужно:

  • Найти все blob:-изображения в редакторе.

  • Конвертировать их в File/Blob.

  • Отправить на сервер через FormData.

  • Заменить blob: на серверные URL после загрузки.


Полный код (jQuery + PHP)

1. Находим blob:-изображения в Froala Editor

javascript
Copy
Download
$(document).ready(function() {
    $('#myForm').on('submit', function(e) {
        e.preventDefault(); // Отменяем стандартную отправку

        // Находим все blob-изображения внутри редактора Froala
        const editor = $('#froalaEditor').data('froala.editor'); // Если Froala инициализирован
        const blobImages = $(editor ? editor.$el : '#froalaEditor').find('img[src^="blob:"]');

        if (blobImages.length === 0) {
            this.submit(); // Если нет blob-изображений, отправляем форму как обычно
            return;
        }

        const formData = new FormData(this); // Основные данные формы

        // Добавляем каждое blob-изображение в FormData
        Promise.all(
            blobImages.map(async (imgElement, index) => {
                const blob = await fetch(imgElement.src).then(res => res.blob());
                formData.append(`images[${index}]`, blob, `image_${index}.png`);
                return { index, element: imgElement };
            })
        ).then(async (images) => {
            // Отправляем FormData на сервер
            const response = await fetch('upload.php', {
                method: 'POST',
                body: formData,
            });
            const data = await response.json();

            if (data.success) {
                // Заменяем blob: на серверные URL
                images.forEach(({ index, element }) => {
                    if (data.savedPaths[index]) {
                        $(element).attr('src', data.savedPaths[index]);
                    }
                });
                this.submit(); // Отправляем форму с обновлёнными URL
            } else {
                alert('Ошибка загрузки изображений: ' + data.error);
            }
        }).catch(error => {
            console.error('Ошибка:', error);
            alert('Не удалось обработать изображения');
        });
    });
});

2. Серверный код (upload.php)

php
Copy
Download
<?php
header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['success' => false, 'error' => 'Invalid request method']);
    exit;
}

$uploadDir = 'uploads/';
if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0755, true);
}

$savedPaths = [];
$errors = [];

// Обрабатываем загруженные файлы
if (!empty($_FILES['images'])) {
    foreach ($_FILES['images']['tmp_name'] as $index => $tmpName) {
        if ($_FILES['images']['error'][$index] !== UPLOAD_ERR_OK) {
            $errors[] = "Ошибка загрузки изображения {$index}";
            continue;
        }

        $ext = pathinfo($_FILES['images']['name'][$index], PATHINFO_EXTENSION) ?: 'png';
        $fileName = uniqid() . '.' . $ext;
        $filePath = $uploadDir . $fileName;

        if (move_uploaded_file($tmpName, $filePath)) {
            $savedPaths[$index] = '/uploads/' . $fileName; // Можно заменить на полный URL
        } else {
            $errors[] = "Не удалось сохранить изображение {$index}";
        }
    }
}

if (empty($errors)) {
    echo json_encode([
        'success' => true,
        'savedPaths' => $savedPaths,
    ]);
} else {
    echo json_encode([
        'success' => false,
        'error' => implode(', ', $errors),
    ]);
}
?>

3. Интеграция с Froala Editor

Если Froala Editor уже загружает изображения на сервер (например, через imageUploadURL), но всё равно оставляет blob: в редакторе, можно:

Вариант 1: Отключить blob: и использовать только серверные URL

javascript
Copy
Download
new FroalaEditor('#froalaEditor', {
    imageUploadURL: '/upload_froala.php', // Серверный обработчик загрузки
    imageUploadParams: { // Доп. параметры (если нужно)
        key: 'your-api-key',
    },
    // Отключаем временные blob-URL
    imagePaste: false,
    imageInsertButtons: ['upload'],
});

Вариант 2: Принудительно заменять blob: после вставки

javascript
Copy
Download
new FroalaEditor('#froalaEditor', {
    events: {
        'image.inserted': function ($img, response) {
            // Если Froala возвращает URL изображения, заменяем blob:
            if (response && response.link) {
                $img.attr('src', response.link);
            }
        },
    },
});

Итог

  1. Проблема:

    • Froala Editor вставляет изображения как blob:, но они не отправляются с формой.

  2. Решение:

    • Перед отправкой формы извлекаем blob:-изображения.

    • Конвертируем их в File и добавляем в FormData.

    • Отправляем на сервер и заменяем blob: на реальные URL.

  3. Дополнительно:

    • Можно настроить Froala Editor на автоматическую загрузку изображений (без blob:).

Теперь форма будет корректно сохранять все изображения! 🎯

Самый простой пример используя лёгкий и простой wysiwyg Вставить изображения и сохранить изображения текст Используя jquery PHP Ajax php

Вот самый простой пример с использованием:
✅ Легкий WYSIWYG-редактор (TinyMCE или Summernote)
✅ Загрузка изображений через AJAX (jQuery)
✅ Сохранение в PHP


📝 1. Подключаем Summernote (простой WYSIWYG)

HTML (index.html)

html
Copy
Download
Run
<!DOCTYPE html>
<html>
<head>
    <title>Простой редактор с загрузкой изображений</title>
    <!-- Подключаем jQuery + Summernote -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-lite.min.js"></script>
</head>
<body>
    <form id="editorForm">
        <textarea id="summernote" name="content"></textarea>
        <button type="submit">Сохранить</button>
    </form>

    <script>
        $(document).ready(function() {
            // Инициализация Summernote
            $('#summernote').summernote({
                height: 300,
                toolbar: [
                    ['style', ['bold', 'italic', 'underline']],
                    ['insert', ['picture']], // Кнопка вставки изображений
                ],
                callbacks: {
                    onImageUpload: function(files) {
                        uploadImage(files[0]); // Загружаем 1 файл
                    }
                }
            });

            // Отправка формы
            $('#editorForm').on('submit', function(e) {
                e.preventDefault();
                const content = $('#summernote').summernote('code');
                
                $.ajax({
                    url: 'save.php',
                    type: 'POST',
                    data: { content: content },
                    success: function(response) {
                        alert('Сохранено!');
                    },
                    error: function() {
                        alert('Ошибка сохранения!');
                    }
                });
            });
        });

        // Загрузка изображения на сервер
        function uploadImage(file) {
            const formData = new FormData();
            formData.append('image', file);

            $.ajax({
                url: 'upload.php',
                type: 'POST',
                data: formData,
                contentType: false,
                processData: false,
                success: function(response) {
                    $('#summernote').summernote('insertImage', response.url); // Вставляем изображение
                },
                error: function() {
                    alert('Ошибка загрузки изображения!');
                }
            });
        }
    </script>
</body>
</html>

🖼️ 2. PHP-обработчик загрузки изображений (upload.php)

php
Copy
Download
<?php
header('Content-Type: application/json');

if (isset($_FILES['image'])) {
    $uploadDir = 'uploads/';
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0777, true);
    }

    $fileName = uniqid() . '.png';
    $filePath = $uploadDir . $fileName;

    if (move_uploaded_file($_FILES['image']['tmp_name'], $filePath)) {
        echo json_encode([
            'success' => true,
            'url' => $filePath // Можно заменить на полный URL (http://site.com/uploads/...)
        ]);
    } else {
        echo json_encode(['success' => false, 'error' => 'Ошибка загрузки']);
    }
} else {
    echo json_encode(['success' => false, 'error' => 'Нет файла']);
}
?>

💾 3. PHP-обработчик сохранения текста (save.php)

php
Copy
Download
<?php
if (isset($_POST['content'])) {
    $content = $_POST['content'];
    file_put_contents('saved_content.html', $content);
    echo 'Текст сохранён!';
} else {
    echo 'Ошибка: нет данных!';
}
?>

🔥 Как это работает?

  1. Пользователь вставляет изображение в Summernote → срабатывает onImageUpload.

  2. Изображение отправляется на upload.php → сохраняется в папку uploads/.

  3. Summernote получает URL изображения и вставляет его в редактор.

  4. При отправке формы весь HTML (с <img src="uploads/...">) сохраняется в saved_content.html.


📂 Структура файлов

text
Copy
Download
/ 
├── index.html       # Форма с редактором
├── upload.php      # Загрузка изображений
├── save.php        # Сохранение текста
├── uploads/        # Папка для картинок
└── saved_content.html # Сохранённый HTML

Улучшения (по желанию):

  • Валидация изображений (проверка $_FILES['image']['type']).

  • Сжатие изображений (imagewebp(), imagejpeg()).

  • Защита от перезаписи (проверка file_exists()).

Теперь у вас есть простой WYSIWYG-редактор с загрузкой изображений! 🚀

Часть кода которая повторяется несколько раз <input class="form-check-input" name="not_post_msg" type="checkbox" value="" id="not_post_msg" checked><label class="form-check-label" for="not_post_msg"> без отправки письма </label> Но только в одном месте работает при нажатие на текст 'без отправки письма' checkbox меняется Возможно при нажатии на label надписи везде включался и выключался checkbox

Проблема в том, что у вас несколько одинаковых checkbox с одинаковыми id и name, но только один из них реагирует на клик по <label>. Это происходит потому, что:

  1. ID должны быть уникальными в HTML-документе

  2. Лейбел связан только с первым чекбоксом, так как ищет элемент по id="not_post_msg"

🔧 Исправленный вариант

html
Copy
Download
Run
<!-- Пример 1 -->
<div class="form-check">
  <input class="form-check-input not-post-msg-checkbox" name="not_post_msg[]" type="checkbox" value="1">
  <label class="form-check-label not-post-msg-label">без отправки письма</label>
</div>

<!-- Пример 2 -->
<div class="form-check">
  <input class="form-check-input not-post-msg-checkbox" name="not_post_msg[]" type="checkbox" value="1">
  <label class="form-check-label not-post-msg-label">без отправки письма</label>
</div>

🛠️ Решение через JavaScript/jQuery

Добавьте этот код:

javascript
Copy
Download
$(document).ready(function() {
  // Обработка клика по любому лейбелу
  $('.not-post-msg-label').click(function() {
    // Находим связанный чекбокс в том же контейнере
    const checkbox = $(this).siblings('.not-post-msg-checkbox');
    // Переключаем состояние
    checkbox.prop('checked', !checkbox.prop('checked'));
  });
});

💡 Почему это работает:

  1. Убрали дублирование id - теперь используем классы

  2. Лейбелы привязаны к своим чекбоксам через структуру DOM

  3. JavaScript обрабатывает клики по всем лейбелам с классом not-post-msg-label

🌟 Дополнительные улучшения:

Если нужно синхронизировать все чекбоксы:

javascript
Copy
Download
$(document).ready(function() {
  $('.not-post-msg-label').click(function() {
    const isChecked = !$(this).siblings('.not-post-msg-checkbox').prop('checked');
    $('.not-post-msg-checkbox').prop('checked', isChecked);
  });
});

Теперь при клике на любой лейбел будут переключаться все чекбоксы одновременно.

Как на jquery добавить что то внутрь div class add но в самый верх быть первым всегда каждый раз если добавлять еще <div class="add"> <li>1</li> </div>
2 / 2

Чтобы добавлять новые элементы в самый верх <div class="add"> с помощью jQuery, используйте метод .prepend().

Пример кода:

javascript
Copy
Download
// Добавляем новый элемент В НАЧАЛО блока .add
$('.add').prepend('<li>Новый элемент (вверху)</li>');

Как это работает:

  1. $('.add') — выбирает все элементы с классом add.

  2. .prepend() — вставляет переданный HTML в начало выбранного элемента (перед всем существующим содержимым).


Пример с кнопкой для добавления:

html
Copy
Download
Run
<div class="add">
  <li>1</li>
</div>

<button id="addNewItem">Добавить элемент</button>

<script>
$(document).ready(function() {
  let counter = 1; // Счётчик для примера
  
  $('#addNewItem').click(function() {
    counter++;
    $('.add').prepend(`<li>${counter} (новый, вверху)</li>`);
  });
});
</script>

Результат:

Каждый новый элемент будет добавляться сверху:

text
Copy
Download
<div class="add">
  <li>3 (новый, вверху)</li>
  <li>2 (новый, вверху)</li>
  <li>1</li>
</div>

Дополнительные варианты:

  1. Если нужно добавить перед определенным элементом — используйте .before():

    javascript
    Copy
    Download
    $('.add li:first').before('<li>Новый элемент перед первым</li>');
  2. Если нужно добавить сложный элемент (например, с обработчиками событий):

    javascript
    Copy
    Download
    const $newItem = $('<li>').text(counter + ' (динамический)').click(function() {
      alert('Клик по новому элементу!');
    });
    $('.add').prepend($newItem);

Теперь новые элементы всегда будут появляться первыми в блоке! 🚀

Делаю вот такой запрос на странице постоянно Но через какое то время начинает Alert срабатывать fail Может ли браузер как то засыпать на странице ? Потому что опрос больше не идет на сервер setInterval('UpdateOrder()', 3000); function UpdateOrder(){ var ordersID = '256'; $.post( 'ajax/post.php', { update_deal_full : ordersID }, function( data ) { console.log(data); },'json').fail(function() { alert( "error" ); }); }

Да, браузер действительно может "засыпать" или приостанавливать выполнение JavaScript, особенно:

  1. Когда вкладка неактивна (Chrome, Firefox и другие замедляют setInterval до ~1 раза в секунду).

  2. При режиме энергосбережения (на мобильных устройствах или ноутбуках).

  3. Если компьютер перешел в спящий режим.

🔧 Как исправить проблему?

1. Используйте visibilitychange для контроля активности вкладки

javascript
Copy
Download
let isTabActive = true;

// Следим за активностью вкладки
document.addEventListener('visibilitychange', function() {
    isTabActive = !document.hidden;
});

function UpdateOrder() {
    if (!isTabActive) return; // Не обновлять, если вкладка неактивна

    const ordersID = '256';
    $.post('ajax/post.php', { update_deal_full: ordersID }, function(data) {
        console.log(data);
    }, 'json').fail(function() {
        console.error("Ошибка запроса"); // Лучше console.error, чем alert
    });
}

// Запускаем интервал
const interval = setInterval(UpdateOrder, 3000);

2. Добавьте проверку ответа сервера

Иногда сервер может блокировать частые запросы (например, из-за rate-limiting).

В post.php добавьте:

php
Copy
Download
header('Content-Type: application/json');
// Чтобы избежать кеширования:
header("Cache-Control: no-cache, must-revalidate");
echo json_encode(['status' => 'success', 'data' => $someData]);

3. Перезапуск интервала при ошибке

Если запросы перестают работать, можно пересоздать setInterval.

javascript
Copy
Download
let retryCount = 0;
const MAX_RETRIES = 3;

function UpdateOrder() {
    const ordersID = '256';
    $.post('ajax/post.php', { update_deal_full: ordersID }, function(data) {
        console.log(data);
        retryCount = 0; // Сброс счетчика ошибок
    }, 'json').fail(function() {
        console.error("Ошибка запроса");
        retryCount++;
        if (retryCount >= MAX_RETRIES) {
            clearInterval(interval);
            console.log("Прекращаем опрос из-за ошибок");
        }
    });
}

let interval = setInterval(UpdateOrder, 3000);

4. Используйте WebSocket вместо setInterval (если возможно)

Если нужны мгновенные обновления, лучше использовать WebSockets или Server-Sent Events (SSE).

Вывод

  • Проблема: Браузер замедляет/останавливает setInterval в фоновых вкладках.

  • Решение:

    • Контролировать активность вкладки (visibilitychange).

    • Обрабатывать ошибки и перезапускать интервал.

    • Использовать WebSockets/SSE для мгновенных обновлений.

Попробуйте эти методы, и запросы должны стабилизироваться! 🚀

Uncaught SyntaxError: Identifier 'UpdateOrder' has already been declared

Ошибка Uncaught SyntaxError: Identifier 'UpdateOrder' has already been declared возникает, когда вы пытаетесь повторно объявить функцию или переменную с тем же именем в одной области видимости.

🔍 Причины ошибки в вашем коде:

  1. Вы определяете функцию UpdateOrder() несколько раз (например, при повторном вызове setInterval или загрузке скрипта).

  2. Возможно, скрипт подключается несколько раз на странице.


Как исправить?

1. Проверьте, что функция объявлена только один раз

Убедитесь, что UpdateOrder() не определяется повторно.

2. Используйте let/const вместо var (если нужно переопределение)

Если функция должна перезаписываться, можно использовать:

javascript
Copy
Download
const UpdateOrder = function() { ... }; // или let

3. Очищайте предыдущий setInterval перед созданием нового

javascript
Copy
Download
// Если interval уже существует, очистите его
if (typeof interval !== 'undefined') {
    clearInterval(interval);
}

// Затем создайте новый
const interval = setInterval(UpdateOrder, 3000);

4. Проверьте дублирование скриптов

Убедитесь, что:

  • Скрипт не подключается несколько раз (например, через <script src="...">).

  • Нет вставки кода в нескольких местах.


🛠 Исправленный код

javascript
Copy
Download
// Объявляем функцию только один раз!
function UpdateOrder() {
    const ordersID = '256';
    $.post('ajax/post.php', { update_deal_full: ordersID }, function(data) {
        console.log(data);
    }, 'json').fail(function() {
        console.error("Ошибка запроса");
    });
}

// Очищаем старый интервал (если есть)
if (window.updateInterval) {
    clearInterval(window.updateInterval);
}

// Запускаем новый интервал
window.updateInterval = setInterval(UpdateOrder, 3000);

💡 Дополнительные советы

  1. Проверьте консоль браузера (F12 → Console) на другие ошибки.

  2. Используйте console.log() для отладки.

  3. Если код вставляется через eval() или динамически, убедитесь, что он не дублируется.

Теперь ошибка Identifier 'UpdateOrder' has already been declared исчезнет! 🚀

Unchecked runtime.lastError: The message port closed before a response was received. Из за чего и как исправить ? И является ли ошибкой ?

Ошибка: Unchecked runtime.lastError: The message port closed before a response was received

🔍 Что это значит?

Эта ошибка возникает в расширениях Chrome (реже — в Firefox) при работе с асинхронными сообщениями между:

  • Фоновым скриптом (background.js)

  • Контент-скриптом (content_script.js)

  • Popup/Options-страницами

Ошибка означает, что порт для обмена сообщениями закрылся раньше, чем пришел ответ на отправленный запрос.


📌 Основные причины

  1. Отправка сообщения, но отсутствие return true в chrome.runtime.sendMessage

    • Если расширение отправляет сообщение, но не получает ответ (например, из-за ошибки в обработчике).

  2. Слишком долгий ответ от chrome.runtime.onMessage

    • Если обработчик сообщения не отвечает вовремя, Chrome закрывает порт.

  3. Использование chrome.tabs.sendMessage к несуществующей вкладке

    • Например, вкладка закрылась до получения ответа.

  4. Неправильная обработка Promise в расширении

    • Если async/await или .then() не обработаны корректно.


🛠 Как исправить?

1. Добавьте return true в обработчик сообщений

javascript
Copy
Download
// В контент-скрипте или фоновом скрипте:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    console.log("Получено сообщение:", request);
    sendResponse({ status: "OK" }); // Ответ серверу
    return true; // ⚠️ Важно: оставить порт открытым для асинхронного ответа
});

2. Убедитесь, что sendResponse вызывается ДО завершения функции

javascript
Copy
Download
// ❌ Плохо (sendResponse после await):
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
    const data = await fetch(...);
    sendResponse(data); // Может быть слишком поздно!
});

// ✅ Правильно (ответ перед await):
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    fetch(...).then(data => sendResponse(data));
    return true; // Разрешаем асинхронный ответ
});

3. Проверьте, существует ли вкладка перед отправкой

javascript
Copy
Download
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
    if (tabs[0]?.id) {
        chrome.tabs.sendMessage(tabs[0].id, { action: "ping" }, (response) => {
            if (chrome.runtime.lastError) {
                console.error("Ошибка:", chrome.runtime.lastError);
            } else {
                console.log("Ответ:", response);
            }
        });
    }
});

4. Обрабатывайте ошибки в Promise

javascript
Copy
Download
chrome.runtime.sendMessage({ action: "getData" }, (response) => {
    if (chrome.runtime.lastError) {
        console.error("Ошибка:", chrome.runtime.lastError);
    } else {
        console.log("Успех:", response);
    }
});

💡 Является ли это критичной ошибкой?

  • Нет, если расширение работает корректно.

  • Да, если из-за этого ломается функционал (например, не приходят ответы).

Ошибка чаще всего влияет только на отладку, но не на пользователей. Однако лучше её починить.


🚀 Итог

  1. Добавьте return true в onMessage.

  2. Убедитесь, что sendResponse вызывается вовремя.

  3. Проверяйте chrome.runtime.lastError.

  4. Закрывайте порты явно, если нужно.

После этих правок ошибка пропадет! ✅

После clearInterval(interval) дальше setInterval не продолжается

Проблема в том, что после вызова clearInterval(interval) интервал действительно прекращает работу, и для его возобновления нужно заново вызвать setInterval(). Вот как это правильно реализовать:

🔧 Причины и решения

1. Интервал не запускается повторно

javascript
Copy
Download
let interval;

function startPolling() {
  interval = setInterval(UpdateOrder, 3000); // Запускаем интервал
}

function stopPolling() {
  clearInterval(interval); // Останавливаем интервал
  interval = null; // Очищаем переменную
}

// Для возобновления нужно снова вызвать:
startPolling(); // Перезапускает интервал

2. Автоматический перезапуск при ошибке (пример)

javascript
Copy
Download
let interval;
let retryCount = 0;
const MAX_RETRIES = 3;

function UpdateOrder() {
  $.post('ajax/post.php', { update_deal_full: '256' })
    .done(function(data) {
      console.log(data);
      retryCount = 0; // Сброс счетчика при успехе
    })
    .fail(function() {
      console.error("Ошибка запроса");
      retryCount++;
      
      if (retryCount >= MAX_RETRIES) {
        stopPolling(); // Останавливаем при многократных ошибках
        setTimeout(startPolling, 10000); // Перезапуск через 10 сек
      }
    });
}

// Первый запуск
startPolling();

3. Контроль состояния интервала

javascript
Copy
Download
function isPollingActive() {
  return interval !== null && interval !== undefined;
}

// Проверка перед действиями
if (!isPollingActive()) {
  startPolling();
}

🛠 Почему так происходит?

  • clearInterval() полностью удаляет таймер, и его нужно создавать заново

  • Переменная interval сохраняет ID таймера, но после очистки становится неактивной

💡 Оптимальное решение

javascript
Copy
Download
class Poller {
  constructor() {
    this.interval = null;
    this.retryCount = 0;
  }

  start() {
    this.interval = setInterval(() => this.execute(), 3000);
  }

  stop() {
    clearInterval(this.interval);
    this.interval = null;
  }

  execute() {
    $.post('ajax/post.php', { update_deal_full: '256' })
      .done(data => {
        console.log(data);
        this.retryCount = 0;
      })
      .fail(() => {
        this.retryCount++;
        if (this.retryCount > 3) {
          this.stop();
          setTimeout(() => this.start(), 10000);
        }
      });
  }
}

// Использование
const poller = new Poller();
poller.start();

// Для остановки
// poller.stop();

📌 Key Points:

  1. После clearInterval() интервал нужно пересоздавать

  2. Лучше использовать класс для управления состоянием

  3. Добавляйте задержку перед перезапуском при ошибках

  4. Всегда очищайте старый интервал перед созданием нового

Теперь ваш интервал будет корректно перезапускаться после остановки!

Форма <input type="file" id="files_to" name="files_to[]" multiple="multiple" class="custom-file-input"> Сейчас когда добавили файл один то если ещё надо добавить файл то добавляется тот файл последний а ранее добавленный пропадает Возможно что можно добавлять файлы каждый раз и они не сбрасывали предыдущие выбранные файлы

Проблема в том, что стандартный <input type="file"> сбрасывает предыдущие файлы при новом выборе. Вот как сделать, чтобы файлы накапливались:

Решение на JavaScript/jQuery

javascript
Copy
Download
// Массив для хранения всех выбранных файлов
let allFiles = [];

$(document).ready(function() {
  $('#files_to').on('change', function(e) {
    // Добавляем новые файлы к уже выбранным
    const newFiles = Array.from(e.target.files);
    allFiles = [...allFiles, ...newFiles];
    
    // Создаем новый DataTransfer и добавляем все файлы
    const dataTransfer = new DataTransfer();
    allFiles.forEach(file => dataTransfer.items.add(file));
    
    // Присваиваем обновленный список файлов input'у
    e.target.files = dataTransfer.files;
    
    // Можно вывести информацию о выбранных файлах
    console.log('Всего файлов:', allFiles.length);
    allFiles.forEach((file, i) => {
      console.log(`${i+1}. ${file.name} (${(file.size/1024).toFixed(2)} KB)`);
    });
  });
});

Альтернативное решение с визуальным отображением

html
Copy
Download
Run
<input type="file" id="files_to" multiple class="custom-file-input">
<div id="file-list"></div>

<script>
$(document).ready(function() {
  const fileList = $('#file-list');
  let allFiles = [];
  
  $('#files_to').on('change', function(e) {
    const newFiles = Array.from(e.target.files);
    allFiles = [...allFiles, ...newFiles];
    
    // Обновляем отображение
    updateFileList();
    
    // Очищаем значение input, чтобы можно было добавить те же файлы снова
    $(this).val('');
  });
  
  function updateFileList() {
    fileList.empty();
    allFiles.forEach((file, index) => {
      fileList.append(`
        <div class="file-item">
          ${file.name} (${(file.size/1024).toFixed(2)} KB)
          <button class="remove-file" data-index="${index}">×</button>
        </div>
      `);
    });
    
    // Обработчик удаления файлов
    $('.remove-file').on('click', function() {
      const index = $(this).data('index');
      allFiles.splice(index, 1);
      updateFileList();
    });
  }
});
</script>

<style>
.file-item {
  padding: 5px;
  margin: 5px 0;
  background: #f5f5f5;
  display: flex;
  justify-content: space-between;
}
.remove-file {
  background: #ff4444;
  color: white;
  border: none;
  cursor: pointer;
}
</style>

Как это работает:

  1. При каждом выборе файлов мы добавляем их в массив allFiles

  2. Используем DataTransfer для обновления списка файлов в input

  3. Для удобства отображаем список выбранных файлов

  4. Добавляем возможность удаления отдельных файлов

Важные моменты:

  1. Для отправки формы нужно использовать FormData:

javascript
Copy
Download
const formData = new FormData();
allFiles.forEach(file => formData.append('files_to[]', file));
  1. Если нужна поддержка старых браузеров, можно использовать полифил для DataTransfer

  2. Максимальное количество файлов ограничено настройками сервера (post_max_size, upload_max_filesize в PHP)

Это решение позволяет:

  • Добавлять файлы в несколько приемов

  • Видеть все выбранные файлы

  • Удалять ненужные файлы перед отправкой

  • Корректно отправлять все файлы на сервер

А как этот ...allFiles, ...newFiles синтаксис читать ?

Отличный вопрос! Этот синтаксис называется spread operator (оператор расширения) в JavaScript. Давайте разберём его подробно.

Что означает ...allFiles, ...newFiles?

Это современный синтаксис ES6, который можно "развернуть" так:

javascript
Copy
Download
// Было:
allFiles = [...allFiles, ...newFiles];

// Эквивалентно:
allFiles = allFiles.concat(newFiles);

// Или по-старому:
allFiles = [].concat(allFiles, newFiles);

Как это работает?

  1. ...allFiles - "разворачивает" массив allFiles на отдельные элементы

  2. ...newFiles - аналогично разворачивает массив newFiles

  3. [...allFiles, ...newFiles] - создаёт новый массив, куда сначала помещает все элементы из allFiles, затем все элементы из newFiles

Пример:

javascript
Copy
Download
const fruits = ['яблоко', 'груша'];
const newFruits = ['апельсин', 'банан'];

const allFruits = [...fruits, ...newFruits];
// Результат: ['яблоко', 'груша', 'апельсин', 'банан']

Почему не использовать concat()?

Spread operator:

  1. Читается более естественно (видно, что происходит)

  2. Может использоваться не только для массивов

  3. Часто работает быстрее в современных браузерах

Где ещё применяется spread operator?

  1. Копирование массивов:

javascript
Copy
Download
const copy = [...original];
  1. Передача элементов в функцию:

javascript
Copy
Download
const numbers = [1, 2, 3];
Math.max(...numbers); // вместо Math.max.apply(null, numbers)
  1. Объединение объектов:

javascript
Copy
Download
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const merged = { ...obj1, ...obj2 }; // { a: 1, b: 2 }

Важно знать:

  • Spread operator создаёт новый массив/объект, а не изменяет существующий

  • Работает во всех современных браузерах (кроме IE11)

  • Может использоваться с любыми итерируемыми объектами (массивы, строки, Set и т.д.)

Этот синтаксис делает код чище и понятнее, поэтому я рекомендую его использовать!

При попытке отправить файлы приходит на сервер пустой $_FILES [_FILES] => Array ( [files_to] => Array ( [name] => Array ( [0] => ) [type] => Array ( [0] => ) [tmp_name] => Array ( [0] => ) [error] => Array ( [0] => 4 ) [size] => Array ( [0] => 0 ) ) )

Проблема с пустым $_FILES возникает из-за неправильной подготовки FormData для отправки. Вот как это исправить:

🔧 Полное решение для отправки накопленных файлов

javascript
Copy
Download
// Массив для хранения файлов
let allFiles = [];

// При изменении input file
$('#files_to').on('change', function(e) {
  const newFiles = Array.from(e.target.files);
  allFiles = [...allFiles, ...newFiles];
  $(this).val(''); // Очищаем input
});

// Отправка формы
$('#myForm').on('submit', function(e) {
  e.preventDefault();
  
  const formData = new FormData(this);
  
  // Удаляем стандартное поле files_to (оно пустое)
  formData.delete('files_to[]');
  
  // Добавляем все накопленные файлы
  allFiles.forEach((file, index) => {
    formData.append(`files_to[${index}]`, file);
  });
  
  // Отправка на сервер
  $.ajax({
    url: 'upload.php',
    type: 'POST',
    data: formData,
    processData: false,
    contentType: false,
    success: function(response) {
      console.log('Файлы отправлены!');
      allFiles = []; // Очищаем массив после отправки
    },
    error: function(xhr) {
      console.error('Ошибка:', xhr.responseText);
    }
  });
});

🛠 Почему это работает:

  1. FormData должна создаваться из формы (new FormData(this))

  2. Удаляем пустое поле files_to[] (которое создается из input)

  3. Добавляем файлы вручную с правильными именами (files_to[0], files_to[1] и т.д.)

  4. Обязательные параметры для AJAX:

    javascript
    Copy
    Download
    processData: false, // Не обрабатывать данные
    contentType: false  // Не устанавливать Content-Type

📌 Серверная часть (PHP)

php
Copy
Download
<?php
header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!empty($_FILES['files_to'])) {
        $uploadedFiles = [];
        
        foreach ($_FILES['files_to']['name'] as $index => $name) {
            if ($_FILES['files_to']['error'][$index] === UPLOAD_ERR_OK) {
                $tmpName = $_FILES['files_to']['tmp_name'][$index];
                $newName = 'uploads/' . uniqid() . '_' . $name;
                
                if (move_uploaded_file($tmpName, $newName)) {
                    $uploadedFiles[] = $newName;
                }
            }
        }
        
        echo json_encode(['success' => true, 'files' => $uploadedFiles]);
    } else {
        echo json_encode(['error' => 'No files uploaded']);
    }
}
?>

💡 Дополнительные проверки:

  1. Лимит загрузки в php.ini:

    ini
    Copy
    Download
    upload_max_filesize = 20M
    post_max_size = 21M
  2. Права на папку uploads:

    bash
    Copy
    Download
    chmod 755 uploads
  3. Проверка MIME-типов (если нужно):

    php
    Copy
    Download
    $allowedTypes = ['image/jpeg', 'image/png'];
    if (!in_array($_FILES['files_to']['type'][$index], $allowedTypes)) {
        // Запретить загрузку
    }

Теперь файлы будут корректно передаваться на сервер без потери данных! 🚀

После отправки как отчистить allFiles ?

Чтобы очистить массив allFiles после успешной отправки на сервер, нужно добавить сброс массива в обработчик успешной отправки. Вот как это правильно сделать:

🔄 Полный код с очисткой после отправки

javascript
Copy
Download
let allFiles = []; // Массив для хранения файлов

// Обработчик отправки формы
$('#myForm').on('submit', function(e) {
  e.preventDefault();
  
  const formData = new FormData(this);
  
  // Добавляем все файлы в FormData
  allFiles.forEach((file, index) => {
    formData.append(`files_to[${index}]`, file);
  });

  $.ajax({
    url: 'upload.php',
    type: 'POST',
    data: formData,
    processData: false,
    contentType: false,
    success: function(response) {
      // 1. Очищаем массив файлов
      allFiles = [];
      
      // 2. Очищаем список отображения файлов (если есть)
      $('#file-list').empty(); 
      
      // 3. Сбрасываем input file
      $('#files_to').val('');
      
      console.log('Файлы отправлены и список очищен!');
    },
    error: function(xhr) {
      console.error('Ошибка отправки:', xhr.responseText);
    }
  });
});

💡 Почему это важно:

  1. allFiles = [] - полностью пересоздает массив

  2. Очистка визуального списка - если вы показываете файлы пользователю

  3. Сброс input - позволяет заново выбирать те же файлы

🎯 Альтернативные способы очистки:

  1. Очистка при закрытии модального окна:

javascript
Copy
Download
$('#modal').on('hidden.bs.modal', function() {
  allFiles = [];
});
  1. Кнопка "Очистить":

javascript
Copy
Download
$('#clearFiles').click(function() {
  allFiles = [];
  $('#file-list').empty();
  $('#files_to').val('');
});
  1. При новом выборе файлов (если нужно сохранять только последние):

javascript
Copy
Download
$('#files_to').on('change', function() {
  allFiles = Array.from(this.files); // Заменяем а не добавляем
});

⚠️ Важные нюансы:

  1. Всегда проверяйте успешность отправки перед очисткой

  2. Для сложных случаев используйте allFiles.length = 0 (менее читаемо, но быстрее для больших массивов)

  3. Если используете Vue/React - очищайте через методы состояния

Теперь ваш файловый менеджер будет корректно очищаться после каждой отправки! 🚀

Если к форме не прикрепить файлы то нужно все равно отправить пустой files_to Где и какую проверку придумать ? formData.delete('files_to[]'); allFiles.forEach(file => formData.append('files_to[]', file));

Чтобы форма всегда отправляла поле files_to (даже пустое), но при этом корректно работала с файлами, можно реализовать следующую проверку:

Оптимальное решение

javascript
Copy
Download
$('#myForm').on('submit', function(e) {
  e.preventDefault();
  const formData = new FormData(this);

  // Всегда удаляем стандартное поле (оно может быть пустым)
  formData.delete('files_to[]');

  // Если есть файлы - добавляем их, если нет - добавляем пустое поле
  if (allFiles.length > 0) {
    allFiles.forEach(file => formData.append('files_to[]', file));
  } else {
    formData.append('files_to[]', ''); // Пустое поле
  }

  $.ajax({
    url: 'upload.php',
    type: 'POST',
    data: formData,
    processData: false,
    contentType: false,
    success: function(response) {
      allFiles = []; // Очищаем после отправки
    }
  });
});

Альтернативный вариант с более строгой проверкой

javascript
Copy
Download
// В обработчике submit:
const hasFiles = allFiles.some(file => file instanceof File);

if (hasFiles) {
  allFiles.forEach(file => formData.append('files_to[]', file));
} else {
  formData.append('files_to[]', new File([], '')); // Пустой файл
}

Серверная обработка (PHP)

php
Copy
Download
if (isset($_FILES['files_to'])) {
  if ($_FILES['files_to']['error'][0] == UPLOAD_ERR_NO_FILE) {
    // Обработка случая, когда файлов нет
    echo "Получен пустой files_to";
  } else {
    // Обработка загруженных файлов
    foreach ($_FILES['files_to']['tmp_name'] as $index => $tmpName) {
      if ($_FILES['files_to']['error'][$index] === UPLOAD_ERR_OK) {
        move_uploaded_file($tmpName, 'uploads/' . $_FILES['files_to']['name'][$index]);
      }
    }
  }
}

Ключевые моменты:

  1. Гарантированная отправка поля - поле files_to всегда присутствует в запросе

  2. Гибкая проверка - учитываются как пустые отправки, так и реальные файлы

  3. Совместимость - работает с любой серверной логикой

  4. Чистый код - понятная и поддерживаемая структура

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

New chat
DeepThink (R1)
Search
AI-generated, for reference only