Всего 125 545 комментариев

Николай Савин
6 часов назад
0
Евгений, вопрос закрыт?
Я на всякий случай уточню. В загрузчике встроена обработка изображений. Можно загруженного фото обрезать, развернуть и т.п. После применения изменений уже сохраняем то, что получилось. Так что делать автоматическое сохранение не вижу смысла.
Ivan K.
6 часов назад
+1
кнопку зеленую (Upload 4 files) надо нажать, чтобы фотки попали в гелерею, сам не сразу сообразил)
FastDevLab
8 часов назад
0
С виду все норм.
1. Большая вероятность, что у вас какой-то конфликт JS (как вариант можно попробовать по одному отключать JS файлики и смотреть. Либо 2-й вариант попробуйте: modx.pro/solutions/25355 (PdoPage без jQuery).
2. Мало вероятно, но все же попробовать можно. У вас в подвале подключена jQuery 2.2.3 (старенькая), закомментируйте ее и попробуйте подключить посвежее
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Евгений
Вчера в 14:29
0
Николай, не работает галерея от слова совсем
n13foxbkru.temp.swtest.ru/download/bag_minishop.mp4
В логах -пусто, права на /assets/images/products 777 выставлял
FastDevLab
Вчера в 12:28
0
Хотя не зря, все равно мой велосипед более гибкий, в будущем может еще что то к нему прикручу.
FastDevLab
Вчера в 11:45
0
А можно ссылочку на сайт (эту страницу с пагинацией)?
Андрей Шевяков
Вчера в 11:30
0
Возможно немного не правильный синтаксис, но суть понятна, где то я делал так в каких то проектах, работало 100%
Андрей Шевяков
Вчера в 11:30
+2
Можно как то так попробовать для нескольких блоков:
{'!PageBlocks' | snippet : [
    'where' => [
        'model_id' => $_modx->resource.parent,
        'constructor_id:IN' => [11,12,13]
    ]
]}
SYAN
Вчера в 11:29
0
код для генерации схем MIGXdb
может кому пригодится или доработается
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>XML Generator for MIGX (Table View)</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            color: #333;
        }
        .config-group {
            margin-bottom: 20px;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 6px;
            background-color: #f9f9f9;
        }
        .config-group label {
            display: block;
            margin: 8px 0 4px;
            font-weight: bold;
            font-size: 0.9em;
        }
        .config-group input {
            width: 100%;
            padding: 8px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        .mjg_input_rows {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 20px;
        }
        .mjg_input_rows th {
            background-color: #f2f2f2;
            text-align: left;
            padding: 12px;
            font-weight: bold;
            border: 1px solid #ddd;
        }
        .mjg_input_rows td {
            padding: 10px;
            border: 1px solid #ddd;
            vertical-align: top;
        }
        .mjg_input_field input,
        .mjg_input_caption input,
        .mjg_input_inputTVtype select {
            width: 100%;
            padding: 8px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        .mjg_input_showintabs label,
        .mjg_input_sortable label {
            display: flex;
            align-items: center;
            gap: 5px;
        }
        .mjg_input_deleterow_action {
            color: #dc3545;
            cursor: pointer;
            font-weight: bold;
        }
        .mjg_input_rows_add_wr {
            margin: 15px 0;
        }
        .mjg_input_rows_add {
            display: inline-block;
            background: #28a745;
            color: white;
            padding: 10px 15px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 0.9em;
        }
        .mjg_input_rows_add:hover {
            background: #218838;
        }
        textarea {
            width: 100%;
            height: 300px;
            font-family: monospace;
            padding: 12px;
            border: 1px solid #ccc;
            border-radius: 4px;
            resize: vertical;
            box-sizing: border-box;
            margin-top: 10px;
            font-size: 0.95em;
        }
        h1 {
            color: #2c3e50;
            margin-bottom: 20px;
        }
        /* Стили для выпадающего списка опций (скрыт по умолчанию) */
        .mjg_input_inputTVtype_inputOptionValues {
            margin-top: 8px;
            display: none;
        }
        .mjg_input_inputTVtype_inputOptionValues_item {
            display: flex;
            gap: 8px;
            margin-bottom: 5px;
        }
        .mjg_input_inputTVtype_inputOptionValues_item input {
            flex: 1;
            padding: 6px;
        }
        .mjg_input_inputTVtype_inputOptionValues_item_delete {
            color: #dc3545;
            cursor: pointer;
            font-weight: bold;
        }
        .mjg_input_inputTVtype_inputOptionValues_add {
            color: #007bff;
            cursor: pointer;
            font-size: 0.85em;
            margin-top: 5px;
        }
    </style>
</head>
<body>
    <h1>Генератор XML для MIGX/MODX (Таблица)</h1>

    <!-- Основные настройки модели -->
    <div class="config-group">
        <label for="modelPackage">Package (model package)</label>
        <input type="text" id="modelPackage" value="mygallery" placeholder="Например: mygallery">

        <label for="objectClass">Class (object class)</label>
        <input type="text" id="objectClass" value="myGallery" placeholder="Например: myGallery">


        <label for="tableName">Table (table)</label>
        <input type="text" id="tableName" value="migx_gallery" placeholder="Например: migx_gallery">
    </div>

    <div class="mjg_input_rows">
        <table>
            <thead>
                <tr>
                    <th>Ключ (key)
<span style="font-size:12px;color:#888;">Например: title</span></th>
                    <th>Тип БД (dbtype)
<span style="font-size:12px;color:#888;">varchar, int и др.</span></th>
                    <th>Точность (precision)
<span style="font-size:12px;color:#888;">Для varchar/int</span></th>
                    <th>PHP-тип (phptype)
<span style="font-size:12px;color:#888;">string, integer и др.</span></th>
                    <th>NULL?</th>
                    <th>Значение по умолчанию</th>
                    <th>Индекс</th>
                    <th></th>
                </tr>
            </thead>
            <tbody id="fieldsContainer">
                <!-- Первая строка по умолчанию -->
                <tr class="mjg_input_row" id="field_1">
                    <td class="mjg_input_field">
                        <input type="text" name="key" placeholder="title" required>
                    </td>
                    <td class="mjg_input_dbtype">
                        <select name="dbtype" onchange="updatePhpType(this)">
                            <option value="varchar">varchar</option>
                            <option value="text">text</option>
                            <option value="int">int</option>
                            <option value="datetime">datetime</option>
                            <option value="tinyint">tinyint</option>
                            <option value="json">json</option>
                        </select>
                    </td>
                    <td class="mjg_input_precision">
                        <input type="text" name="precision" placeholder="255">
                    </td>
                    <td class="mjg_input_phptype">
                        <select name="phptype" required>
                            <option value="string">string</option>
                            <option value="integer">integer</option>
                            <option value="datetime">datetime</option>
                            <option value="json">json</option>
                        </select>
                    </td>
                    <td class="mjg_input_null">
                        <label><input type="checkbox" name="null" checked> Да</label>
                    </td>
                    <td class="mjg_input_default">
                        <input type="text" name="default" placeholder="0">
                    </td>
                    <td class="mjg_input_index">
                        <select name="index">
                            <option value="">—</option>
                            <option value="index">index</option>
                            <option value="fulltext">fulltext</option>
                                                        <option value="unique">unique</option>
                        </select>
                    </td>
                    <td class="mjg_input_deleterow">
                        <span class="mjg_input_deleterow_action" onclick="removeField('field_1')">X</span>
                    </td>
                </tr>
            </tbody>
        </table>
        <div class="mjg_input_rows_add_wr">
            <div class="mjg_input_rows_add" onclick="addField()">Добавить строку</div>
        </div>
    </div>

    <!-- Кнопка генерации XML -->
    <div style="margin: 20px 0;">
        <button type="button" onclick="generateXML()" style="
            background: #007bff;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 1em;
        ">Сгенерировать XML</button>
    </div>

    <h2>Результат (XML)</h2>
    <textarea id="output" placeholder="Здесь появится сгенерированный XML..." readonly></textarea>

    <script>
        let fieldCount = 1; // Начинаем с 1, т.к. первая строка уже есть

        function addField() {
            fieldCount++;
            const container = document.getElementById('fieldsContainer');

            const newRow = document.createElement('tr');
            newRow.className = 'mjg_input_row';
            newRow.id = `field_${fieldCount}`;

            newRow.innerHTML = `
                <td class="mjg_input_field">
                    <input type="text" name="key" placeholder="title" required>
                </td>
                <td class="mjg_input_dbtype">
                    <select name="dbtype" onchange="updatePhpType(this)">
                        <option value="varchar">varchar</option>
                        <option value="text">text</option>
                        <option value="int">int</option>
                        <option value="datetime">datetime</option>
                        <option value="tinyint">tinyint</option>
                        <option value="json">json</option>
                    </select>
                </td>
                <td class="mjg_input_precision">
                    <input type="text" name="precision" placeholder="255">
                </td>
                <td class="mjg_input_phptype">
                    <select name="phptype" required>
                        <option value="string">string</option>
                        <option value="integer">integer</option>
                        <option value="datetime">datetime</option>
                        <option value="json">json</option>
                    </select>
                </td>
                <td class="mjg_input_null">
                    <label><input type="checkbox" name="null" checked> Да</label>
                </td>
                <td class="mjg_input_default">
                    <input type="text" name="default" placeholder="0">
                </td>
                <td class="mjg_input_index">
                    <select name="index">
                        <option value="">—</option>
                        <option value="index">index</option>
                        <option value="fulltext">fulltext</option>
                        <option value="unique">unique</option>
                    </select>
                </td>
                <td class="mjg_input_deleterow">
                    <span class="mjg_input_deleterow_action" onclick="removeField('field_${fieldCount}')">X</span>
                </td>`;

            container.appendChild(newRow);
        }

        function removeField(id) {
            const el = document.getElementById(id);
            if (el) el.remove();
        }

        function updatePhpType(selectEl) {
            const dbtype = selectEl.value;
            const row = selectEl.closest('tr');
            const phptypeSelect = row.querySelector('select[name="phptype"]');


            let suggestedType = 'string';
            switch (dbtype) {
                case 'int':
                case 'tinyint':
                    suggestedType = 'integer';
                    break;
                case 'datetime':
                    suggestedType = 'datetime';
                    break;
                case 'json':
                    suggestedType = 'json';
                    break;
            }
            phptypeSelect.value = suggestedType;
        }

        function escapeXml(str) {
            if (typeof str !== 'string') return '';
            return str
                .replace(/&/g, '&')
                .replace(/</g, '<')
                .replace(/>/g, '>')
                .replace(/"/g, '"')
                .replace(/'/g, ''');
        }

        function generateXML() {
            // Получаем основные параметры
            const modelPackage = escapeXml(document.getElementById('modelPackage').value.trim() || 'mytable');
            const objectClass = escapeXml(document.getElementById('objectClass').value.trim() || 'myTable');
            const tableName = escapeXml(document.getElementById('tableName').value.trim() || 'migx_table');

            const rows = document.querySelectorAll('#fieldsContainer tr.mjg_input_row');
            const xmlLines = [];

            // Заголовок XML
            xmlLines.push('<?xml version="1.0" encoding="UTF-8"?>');
            xmlLines.push(`<model package="${modelPackage}" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">`);
            xmlLines.push(`    <object class="${objectClass}" table="${tableName}" extends="xPDOSimpleObject">`);


            // Обработка каждой строки таблицы
            rows.forEach(row => {
                const keyInput = row.querySelector('input[name="key"]');
                const key = keyInput ? keyInput.value.trim() : '';

                // Пропускаем строку, если ключ не указан
                if (!key) {
                    console.warn('Пропущена строка без ключа:', row);
                    return;
                }

                let fieldXml = `        <field key="${escapeXml(key)}"`;

                const dbtype = row.querySelector('select[name="dbtype"]').value;
                if (dbtype) fieldXml += ` dbtype="${escapeXml(dbtype)}"`;

                const precision = row.querySelector('input[name="precision"]').value.trim();
                if (precision) fieldXml += ` precision="${escapeXml(precision)}"`;

                const phptype = row.querySelector('select[name="phptype"]').value;
                if (phptype) fieldXml += ` phptype="${escapeXml(phptype)}"`;

                const nullCheckbox = row.querySelector('input[name="null"]');
                const nullVal = nullCheckbox.checked ? 'true' : 'false';
                fieldXml += ` null="${nullVal}"`;

                const defaultVal = row.querySelector('input[name="default"]').value.trim();
                if (defaultVal) fieldXml += ` default="${escapeXml(defaultVal)}"`;

                const indexVal = row.querySelector('select[name="index"]').value;
                if (indexVal) fieldXml += ` index="${escapeXml(indexVal)}"`;
                
                fieldXml += ' />';
                xmlLines.push(fieldXml);
            });

            // Добавляем стандартные агрегации
            xmlLines.push('        <aggregate alias="Resource" class="modResource" local="resource_id" foreign="id" cardinality="one" owner="foreign" />');
            xmlLines.push('        <aggregate alias="Creator" class="modUser" local="createdby" foreign="id" cardinality="one" owner="foreign" />');


            // Закрывающие теги
            xmlLines.push('    </object>');
            xmlLines.push('</model>');


            // Выводим результат в текстовое поле
            document.getElementById('output').value = xmlLines.join('\n');
        }

        // Инициализация: добавляем обработчик для кнопки генерации
        document.addEventListener('DOMContentLoaded', () => {
            document.querySelector('.mjg_input_rows_add').addEventListener('click', addField);
        });
    </script>
</body>
</html>
FastDevLab
Вчера в 11:27
0
Выводит только 1 блок (даже если указываешь, несколько) — получается не совсем то
Андрей Шевяков
Вчера в 11:18
0
Вот так же можно выводить из коробки:
{'!PageBlocks' | snippet : [
    'where' => [
        'model_id' => $_modx->resource.parent, // id нужного ресурса
        'constructor_id' => '11', // id блока из списка созданных блоков 
    ],
]}
FastDevLab
Вчера в 09:03
+1
а так это работает только если сайт тоже работает на твоём же компе, как делают некоторые локальную разработку на базе XAMPP, open server и прочих Denwer-ов. — Так я не локально разрабатываю. Сайты (их много, т.к. не только мои) на шаред хостингах (причем разных, дата центры в основном в МСК и Питере) (не VPS) — и у меня мой метод работает (именно на внешнем хостинге, на локальных соответственно тоже).
Кстати говоря, я пока не встречал проблем скачивания на своих сайтах. Кроме случаев, когда изредка лагает репозиторий, и повторная попытка через пару минут пока помогает.
У меня регулярно такие проблемы, в основном с большими пакетами типа TinyMCE RTE.
Ivan K.
28 января 2026, 23:12
+1
Кстати говоря, я пока не встречал проблем скачивания на своих сайтах. Кроме случаев, когда изредка лагает репозиторий, и повторная попытка через пару минут пока помогает.


У меня на шаред-хостингах тоже все нормально скачивается, а вот на VDS один за другим перестает.

И мой метод скорее всего на шаред-хостинге работать не будет, на шареде порты закрыты и не дают законектиться
Дима Касаткин
28 января 2026, 22:59
0
Как будто мы вообще про разное говорим. Если у тебя при подключении к VPN начинают скачиваться пакеты в modx, значит твой сайт подключается к vpn и использует шлюз из другой сети для выхода в интернет, а так это работает только если сайт тоже работает на твоём же компе, как делают некоторые локальную разработку на базе XAMPP, open server и прочих Denwer-ов. В статье речь о том, чтобы заставить сайт, лежащий на внешнем хостинге, с которого не работает скачивание пакетов, подключить к прокси, через который дополнения (пакеты) для CMS MODX начнут скачиваться нормально.

Кстати говоря, я пока не встречал проблем скачивания на своих сайтах. Кроме случаев, когда изредка лагает репозиторий, и повторная попытка через пару минут пока помогает.
Сергей Карпович
28 января 2026, 22:31
0
Отлично
Михаил
28 января 2026, 20:11
0
Понял в чем дело ) Чекбокс один выводился. Переписал вывод — норм. Сергей, спасибо за подсказки!
Михаил
28 января 2026, 20:11
0
Понял в чем дело ) Чекбокс один выводился. Переписал вывод — норм. Сергей, спасибо за подсказки!
Мария
28 января 2026, 19:42
0
Павел, спасибо за ответ. Скопировала код на сайт, но не работает.