403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/burlakastudio.realcommenter/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/burlakastudio.realcommenter/talk_form.js
'use strict';

/**
 * Модуль "Полноценные Комментарии D7" под Битрикс
 * Официальный сайт модуля: www.realcommenter.com
 * Официальный сайт разработчика: burlaka.studio
 * Автор и разработчик: Алексей Бурлака (AlexeyGfi) -> alexeygfi@gmail.com
 */

function realcommenter_forms_scan_and_init() {

    /**
     * Ищем все не проинициализиваронные формы
     */
    let forms = document.querySelectorAll(
        realcommenter_get_selector('tree')
        + ' ' + realcommenter_get_selector('form')
        + ':not(._ambushed)'
        + ':not([data-inited])');

    forms.forEach(function (item) {
        realcommenter_form_init(item);
    });
}

window.addEventListener('load', realcommenter_forms_scan_and_init);
document.addEventListener('form_placed', realcommenter_forms_scan_and_init);

function realcommenterFormAutoReambush() {
    let links =
        document.querySelectorAll(
            realcommenter_get_selector('comment')
            + realcommenter_get_selector('response_to_autoreambush')
            + ' [data-zero]'
            + ':not([data-reambushed])'
        )

    links.forEach(link => {
        link.setAttribute('data-reambushed', '1');
        link.setAttribute('data-form-silent', '1');
        link.click();
    });

}

/**
 * Инициализируем форму комментирования
 * @param form
 */
function realcommenter_form_init(form) {

    // Страховка
    if (form.hasAttribute('data-inited')) {
        return;
    }

    // Поля ввода
    let inputs = form.querySelectorAll(realcommenter_get_selector('form_inputs'));
    inputs.forEach(function (item) {
        item.addEventListener('change', realcommenter_form_memorizer);
    });

    // Рейтинг
    let ratingWrappers = form.querySelectorAll('.itape_rating'/*realcommenter_get_selector('form_inputs')*/);
    ratingWrappers.forEach(function (wraper) {
        let monitor = wraper.querySelector('[data-shape]');
        let shapes = wraper.querySelectorAll('[data-shape] > *');
        let field = wraper.querySelector('[type="hidden"][data-input][data-addit-id]');

        if (!monitor || !shapes.length || !field) {
            return;
        }

        monitor.setAttribute('data-value', field.value);

        let proxyOptions = {
            monitor: monitor,
            field: field
        };

        shapes.forEach(shape => {
            let shapeCallback = realcommenterRatingProcessCallback.bind(shape, proxyOptions);
            shape.addEventListener('mouseover', shapeCallback);
            shape.addEventListener('click', shapeCallback);
        });

        // item.addEventListener('change', realcommenter_form_memorizer);
    });

    // Экшн-элементы
    let submits = form.querySelectorAll('[data-submit]');
    submits.forEach(function (item) {
        item.addEventListener('click', realcommenter_form_action.bind(item, item.getAttribute('data-submit'), false));
    });

    // Комментарий отмечаем как такой, что в нём открыта форма комментирования
    let comment_obj = form.closest(realcommenter_get_selector('comment'));
    if (comment_obj) {
        comment_obj.classList.toggle('_incomment', true);
    }

    // Кнопка закрытия формы
    let closer = form.querySelector(realcommenter_get_selector('form_closer'));
    if (closer) {
        closer.addEventListener('click', realcommenter_form_close.bind(closer, form));
    }

    // Нужна ли загрузка формы авторизации
    let bf_auth = form.querySelector(realcommenter_get_selector('form_auth'));
    if (bf_auth) {
        realcommenter_auth_init(bf_auth);
    }

    // Во время режима редактирования - область уже загруженных файлов
    let files_to_edit = form.querySelectorAll(
        '.brf_edit_uploads [' + realcommenter_get_selector('image_gallery_initer_attr') + '],.brf_edit_uploads [data-file-id]'
    );
    if (files_to_edit.length) {
        files_to_edit.forEach(function (item) {

            let del_obj = document.createElement('del');
            item.appendChild(del_obj);

            let ins_obj = document.createElement('ins');
            del_obj.appendChild(ins_obj);
            ins_obj.addEventListener('click', function () {
                this.classList.toggle('_marked_to_del');
            }.bind(item));

        });
    }

    // Кнопка загрузчика файлов
    let upload_picker = form.querySelector(realcommenter_get_selector('upload_picker'));
    if (upload_picker) {
        if (typeof window['realcommenter_dragndrop_ajax_request'] === 'undefined') {
            realcommenter_drag_n_drop_init_JS(function () {
                this.addEventListener('click', realcommenter_dragndrop_ajax_request);
            }.bind(upload_picker));
        } else {
            upload_picker.addEventListener('click', realcommenter_dragndrop_ajax_request);
        }
    }

    // Визуальный редактор
    let editor_area = form.querySelector(realcommenter_get_selector('form_editor_area'));
    if (editor_area && editor_area.hasAttribute('data-html-editor')) {
        BX.loadScript(
            realcommenter_get_jscss_url('talk_editor.js'),
            function (editorArea) {

                //this - наша форма

                /**
                 * Нужно получить html-код для проброса в редактор
                 * Это либо textarea (и его value) + после чтения textarea удаляем
                 * ...либо innerHTML
                 */

                let _content;

                let _textarea = editorArea.querySelector('textarea');
                if (_textarea) {
                    _content = _textarea.value;
                } else {
                    _content = editorArea.innerHTML;
                }

                editorArea.innerHTML = '';

                let node_to_id = this.getAttribute(realcommenter_get_selector('form_attribute_to'));
                let node_to_target = this.getAttribute(realcommenter_get_selector('form_attribute_target'));

                realcommenterHtmlEditorPlaceAndInit(
                    editorArea,
                    'RCM_EDITOR_' + node_to_id + '_' + node_to_target,
                    _content,
                    form.hasAttribute('data-silent-mode')
                );

            }.bind(form, editor_area)
        );

    } else {
        if (!form.hasAttribute('data-silent-mode')) {
            setTimeout(realcommenterFormActivateTextfield.bind(this, form.parentNode), 50);
        }
    }

    // reCaptcha2
    let talk_obj = form.closest(realcommenter_get_selector('tree'));
    if (talk_obj && BX.message['REALCOMMENTER_RECAPTCHA2_SITEKEY']) {
        BX.loadScript(
            realcommenter_get_jscss_url('recaptcha2.js'),
            function () {
                if (
                    typeof window['realcommenter_recaptcha2_cpu'] !== 'undefined'
                    && window['realcommenter_recaptcha2_cpu']
                ) {
                    window['realcommenter_recaptcha2_cpu']();
                }
            }.bind()
        );
    }

    /**
     * reCaptcha3
     *
     * При инициализации третьей версии нам нужно *один* раз получить токен
     * и дальше уже с ним работать
     */

    if (talk_obj && BX.message['REALCOMMENTER_RECAPTCHA3_SITEKEY']) {
        BX.loadScript(
            realcommenter_get_jscss_url('recaptcha3.js'),
            function () {
                if (
                    typeof window['realcommenter_recaptcha3_cpu'] !== 'undefined'
                    && window['realcommenter_recaptcha3_cpu']
                ) {
                    window['realcommenter_recaptcha3_cpu']();
                }
            }.bind()
        );
    }

    form.setAttribute('data-inited', '1');

}

function realcommenterRatingProcessCallback(proxyOptions) {
    // this -- our single shape
    proxyOptions.field.value = +this.getAttribute('data-value');
    proxyOptions.monitor.setAttribute('data-value', proxyOptions.field.value);
}

function realcommenter_form_action(action, skip_recaptcha3) {

    let _form = this.closest(realcommenter_get_selector('form'));
    let formData = realcommenter_form_parse_form(_form);
    if (!Object.keys(formData).length) {
        return false;
    }

    if (
        typeof realcommenter_recaptcha3_sitekey !== 'undefined'
        && realcommenter_recaptcha3_sitekey()
        && !skip_recaptcha3
    ) {
        realcommenter_recaptcha3_cpu(realcommenter_form_action.bind(this, action, true));
        return;
    }

    // Чистим возможные ошибки внутри
    realcommenter_form_find_and_destroy(_form, '.' + realcommenter_get_selector('form_error_area_classname'));

    // Снимаем форме возможный css-класс о том, что внутри формы есть ошибки
    _form.classList.toggle(realcommenter_get_selector('form_has_errors'), false);

    let data = {
        request_type: action,
        form_data: formData,
        target_node: _form.getAttribute(realcommenter_get_selector('form_attribute_to')),
        target_position: _form.getAttribute(realcommenter_get_selector('form_attribute_target'))
    };

    if (action === 'add') {
        data['browserTitle'] = document.title;
        let h1 = document.querySelector('h1');
        if (h1) {
            data['h1Title'] = h1.innerText;
        }
    }

    realcommenter_ajaxion.bind(this, {
        url: '/bitrix/admin/burlakastudio.realcommenter.talk_form.php',
        onsuccess: realcommenter_form_ajaxed_processor,
        data: data
    })();

}

function realcommenter_form_ajaxed_processor(result) {

    if (typeof result['ERROR'] !== 'undefined' && Object.keys(result['ERROR']).length) {

        if (typeof result['request']['target_node'] !== 'undefined' && result['request']['target_node']) {

            let _selector = '#FORM_SELECTOR#[#FORM_TO_ATTRIBUTE#="#TARGET_NODE#"]';
            _selector = _selector.replace(/#FORM_SELECTOR#/, realcommenter_get_selector('form_'));
            _selector = _selector.replace(/#FORM_TO_ATTRIBUTE#/, realcommenter_get_selector('form_attribute_to'));
            _selector = _selector.replace(/#TARGET_NODE#/, result['request']['target_node']);

            let _form = document.querySelector(_selector);
            if (!_form) {
                return;
            }

            _form.classList.toggle(realcommenter_get_selector('form_has_errors'), true);

            let _messages = [];
            _messages.push(result['ERROR']);

            if (result['STOP_FILTER_WORDS']) {
                _messages.push(
                    BX.message('itape_filter_fired_on')
                    + '<strong>' + result['STOP_FILTER_WORDS'].join('</strong>, <strong>')
                    + '</strong>'
                );
            }

            if (result['STOP_TAGS']) {
                _messages.push(
                    BX.message('itape_filter_by_tag_fired_on')
                    + '<strong>' + result['STOP_TAGS'].join('</strong>, <strong>')
                    + '</strong>'
                );
            }

            realcommenter_form_notice_from_object(_messages, _selector, realcommenter_get_selector('form_error_area_classname'));
        }

        return;

    }

    if (typeof result['MSG_OF_RESULT'] !== 'undefined' && result['MSG_OF_RESULT']) {

        /**
         * Пришло сообщение, которое нужно опубликовать в форме.
         * Например, после отправки нового комментария, который отправлен, но в неактивном состоянии
         */

        if (
            typeof result['request']['target_node'] !== 'undefined'
            || typeof result['request']['target_position'] !== 'undefined'
        ) {

            let _form = realcommenter_find_form_by_to_and_target(result['request']['target_node'], result['request']['target_position']);

            if (_form) {

                /**
                 * Вычищаем лишнее,
                 * находим бади
                 */

                let body_for_msg = null;

                _form.children.forEach = [].forEach;
                _form.children.forEach(function (item) {

                    if (
                        !~item.className.indexOf('brf_header')
                        && !~item.className.indexOf('brf_body')
                    ) {
                        item.parentNode.removeChild(item);
                        return;
                    }

                    if (~item.className.indexOf('brf_body')) {
                        body_for_msg = item;
                    }
                });

                if (body_for_msg) {
                    body_for_msg.innerHTML = result['MSG_OF_RESULT'];
                }

            }
        }

        return;
    }

    switch (result['request']['request_type']) {
        case 'save' :
            console.log('save');
            break;
        case 'preview' :
            console.log('preview');
            break;
        case 'add' :

            /**
             * Добавлен новый комментарий, result[ 'RESULT' ]  содержит его id
             * Пользователь, всё-равно где находится (постраничка, подгрузка порциями, вверху, внизу)
             * ...должен увидеть свой комментарий.
             *
             * Воспользуемся механизмом expand-а комментария, он как раз нам подходит.
             *      • создаём контейнер для отображения комментария;
             *      • скроллим к нему;
             *      • пинаем подгрузку.
             */

            if (
                typeof result['RESULT'] === 'undefined' || !result['RESULT']
                || typeof result['request']['talk_id'] === 'undefined' || !result['request']['talk_id']
            ) {
                return;
            }

            /**
             * Если это ответ на комментарий - даём код комментария
             * ...иначе позицию формы из нулевого уровня
             */

            realcommenter_show_added_comment(result['RESULT'], result['request']['talk_id'], (
                (result['request']['target_node'] && parseInt(result['request']['target_node']))
                    ? result['request']['target_node']
                    : result['request']['target_position']
            ));

            if (result['request']['target_position']) {
                realcommenter_form_closer_ping({
                    talk_id: result['request']['talk_id'],
                    target_position: result['request']['target_position']
                });
            }

            break;
        case 'edit' :

            /**
             * Отредактирован комментарий, result[ 'RESULT' ]  содержит его id
             * Нужно перечитать комментарий
             *
             * Воспользуемся механизмом expand-а комментария, он как раз нам подходит.
             */

            if (
                typeof result['RESULT'] === 'undefined' || !result['RESULT']
                || typeof result['request']['talk_id'] === 'undefined' || !result['request']['talk_id']
            ) {
                return;
            }

            let any_child = document.querySelector(
                realcommenter_get_selector('comment')
                + realcommenter_get_selector('comment_id') + result['RESULT']
                + ' *:first-child'
            );

            if (any_child) {

                // Нужно подскроллить, потому что форма редактирования находилась значительно ниже комментария
                let comment_obj = document.querySelector(
                    realcommenter_get_selector('comment')
                    + realcommenter_get_selector('comment_id') + result['RESULT']
                );

                realcommenter_expand_branch.bind(any_child, {
                    scroll_to_new_comment: 1
                })();
            }

            break;

        default:
            console.log('undefined action');
    }

}

function realcommenter_find_and_expand(commentId) {
    let any_child = document.querySelector(
        realcommenter_get_selector('comment')
        + realcommenter_get_selector('comment_id') + commentId
        + ' *:first-child'
    );

    if (any_child) {
        // Нужно подскроллить, потому что форма редактирования находилась значительно ниже комментария
        let comment_obj = document.querySelector(
            realcommenter_get_selector('comment')
            + realcommenter_get_selector('comment_id') + commentId
        );

        realcommenter_expand_branch.bind(any_child, {
            scroll_to_new_comment: 1
        })();
    }
}

function realcommenter_find_form_by_to_and_target(form_to, form_target) {

    if (!form_to && !form_target) {
        return;
    }

    let _form = false;

    if (form_target) {

        _form = document.querySelector(
            realcommenter_get_selector('form')
            + '[data-form-target="' + form_target + '"]'
        );

    }

    if (!_form && form_to) {
        _form = document.querySelector(
            realcommenter_get_selector('form')
            + '[data-form-to="' + form_to + '"]'
        );
    }

    return _form;

}

function realcommenter_form_pull() {
    //this - наша ссылка.

    /**
     * Ситуации:
     *      • даём ответ на комментарий (есть родительский контейнер с кодом комментария)
     *      • публикуем комментарий перед обсуждением
     *      • публикуем комментарий после обсуждения
     *      +
     *      • редактируем комментарий
     */

    let comment_id = '';
    let comment_target = '';

    if (this.getAttribute('data-zero')) {
        let add_parent = this.closest(realcommenter_get_selector('add_node'));
        if (add_parent) {
            comment_target = add_parent.getAttribute('data-new-comment');
        }

    } else {

        let parent_comment = realcommenter_get_closest_comment(this);
        if (!parent_comment) {
            return false;
        }

        let comment_id_matches = parent_comment.getAttribute('id');
        comment_id_matches = comment_id_matches.match(/[0-9]+/);

        if (!comment_id_matches) {
            return false;
        }

        comment_id = comment_id_matches.shift();

    }

    if (!comment_id && !comment_target) {
        return;
    }

    // Нужно число! Потому что BX.ajax потом из false делает "false"
    let edit_form = +this.hasAttribute('data-to-edit');

    realcommenter_ajaxion.bind(this, {
        url: '/bitrix/admin/burlakastudio.realcommenter.talk_form.php',
        onsuccess: realcommenter_form_place,
        data: {
            request_type: 'get',
            comment_id: comment_id,
            comment_target: comment_target,
            edit_form: edit_form,
            /**
             * Чтобы не подсвечивалось поле ввода (.focus)
             * ...например, у нас автораскрытие форм и форма внизу обсуждения дёргает нас на себя
             */
            silent_mode: +this.hasAttribute('data-form-silent')
        }
    })();
}

function realcommenter_form_place(result) {

    if (typeof result['ERROR'] !== 'undefined' && Object.keys(result['ERROR']).length) {
        console.log('ERROR');
        console.log(result);
        return;
    }

    if (result['FORM_HTML'] !== 'undefined' && result['FORM_HTML']) {

        let commentId = result['request']['comment_id'];
        let commentTarget = result['request']['comment_target'];
        let talkId = result['request']['talk_id'];

        let talkObj = realcommenter_get_talk_by_id(talkId);

        if (talkObj && (commentTarget || commentId)) {

            /**
             * Либо комментарий в нулевой уровень (приоритет)
             * ...либо у нас ответ на какой-то другой комментарий
             */

            let targetBlock = null;

            if (commentTarget) {
                targetBlock = talkObj.querySelector(
                    realcommenter_get_selector('add_node')
                    + '[data-new-comment="' + commentTarget + '"] + '
                    + ' ' + realcommenter_get_selector('subnode')
                );

            } else {

                /**
                 * Если мы даём ответ на какой-то комментарий,
                 * форму интегрируем перед остальными ответами, чтобы их отображение
                 * не зависело от наших действий
                 */

                let commentRowObj = talkObj.querySelector(
                    realcommenter_get_selector('comment') + '[id="answercontainer_' + commentId + '"]'
                );

                if (commentRowObj) {

                    targetBlock = commentRowObj.querySelector(
                        realcommenter_get_selector('comment')
                        + ' > ' + realcommenter_get_selector('subnode')
                    );

                    if (targetBlock.children.length) {
                        let forFormObj = document.createElement('div');
                        forFormObj.className = realcommenter_get_selector_simple('form_tmp_wrapper');
                        targetBlock.insertBefore(forFormObj, targetBlock.children[0]);

                        targetBlock = forFormObj;
                    }
                }
            }

            if (targetBlock) {
                targetBlock.innerHTML = result['FORM_HTML'];

                let event = new CustomEvent('form_placed', {
                        bubbles: true,
                        cancelable: true,
                        detail: targetBlock
                    }
                );

                if (!+result['request']['silent_mode']) {
                    if (!!+result['request']['edit_form']) {
                        realcommenter_tool_scrollTo(targetBlock, -100);
                    }

                }

                document.dispatchEvent(event);
            }

        }

    }
}

/**
 * Эта функция используется тогда, когда посетитель кликнул на ссылку добавления комментария "в виде формы",
 * открылась форма и чтобы оправдать его ожидания (он же кликал на текстовое поле),
 * нужно зафокусировать первое текстовое поле на его пути
 */
function realcommenterFormActivateTextfield(parent_obj) {

    let form_obj = parent_obj.querySelector(realcommenter_get_selector('form'));

    if (!form_obj) {
        return;
    }

    // Первое, что встречается по пути
    let text_obj = form_obj.querySelector('input[type="text"], textarea');
    if (text_obj) {
        text_obj.focus();
    }

}

function realcommenter_form_notice_from_object(messages_tree, obj_css_selector, css_class) {

    if (!messages_tree || !obj_css_selector) {
        return;
    }

    if (!css_class) {
        css_class = 'errors';
    }

    let _message = [];
    for (let e in messages_tree) {
        if (!messages_tree.hasOwnProperty(e)) {
            continue;
        }

        _message.push(messages_tree[e]);
    }

    if (obj_css_selector) {

        let target_obj = false;

        /**
         * Нам могут передать и сразу объект
         */
        if (obj_css_selector instanceof HTMLElement) {
            target_obj = obj_css_selector;
        } else {
            target_obj = document.querySelector(obj_css_selector);
        }

        if (target_obj) {

            let msg_obj = document.createElement('div');
            msg_obj.className = css_class;
            msg_obj.innerHTML = '<div>' + _message.join('</div><div>') + '</div>';
            target_obj.appendChild(msg_obj);

        }

    } else {
        console.log(message.join('\n'));
    }
}

function realcommenter_form_parse_form(_form) {

    if (!_form) {
        return false;
    }

    if (!realcommenter_form_valid(_form)) {
        return false;
    }

    let _result = {};

    // Поля ввода
    let inputs = _form.querySelectorAll(realcommenter_get_selector('form_inputs'));
    inputs.forEach(function (item) {

        /**
         * Ситуация:
         * визуальный редактор Битрикса, ввели что-то внутрь и сразу нажали отправить комментарий.
         *
         * Визуальный редактор не успевает выбросить наружу текст и валидатор говорит: нет значения,
         * ...хотя оно фактически внесено
         *
         * !!! Но учитываем, что редактор может быть в режиме html
         */

        let _value = '';

        if (~item.id.indexOf('RCM_EDITOR')) {

            if (window[item.id].sEditorMode === 'code') {
                _value = item.value;
            } else {
                _value = window[item.id].GetEditorContent();
            }

        } else if (item.value) {
            _value = item.value;
        }

        if (!_value) {
            return;
        }

        /**
         * Нужно обеспечить это:
         *
         * form_data[   ADDI[1]   ]
         * form_data[   ADDI   ]   [1]
         *
         * form_data[   ADDI   ]
         * form_data[   ADDI   ]   [1][]
         */

        let inputNameRaw = item.getAttribute('data-input');
        let baseName = inputNameRaw.match(/^[^\[]+/)[0];
        let deepParts = inputNameRaw.match(/\[([^\]]*)\]/g);

        if (!deepParts || !deepParts.length) {
            _result[baseName] = _value;
        } else {

            // Here is accumulation effect possible
            if (typeof _result[baseName] === 'undefined') {
                _result[baseName] = {};
            }

            let scopeDeep = _result[baseName];

            deepParts.forEach((deep, index, arr) => {
                deep = deep.replace(/(\[|\])/g, '');

                // final step
                if (index >= arr.length - 1) {
                    if (Array.isArray(scopeDeep)) {
                        scopeDeep.push(_value);
                    } else {
                        scopeDeep[deep] = _value;
                    }
                } else {
                    let nextDeep = arr[index + 1].replace(/(\[|\])/g, '');

                    if (typeof scopeDeep[deep] === 'undefined') {
                        /**
                         * Next depth type depends to the next value -
                         * number or empty (tail, accumulation by [])
                         */
                        if (nextDeep === '' || isFinite(+nextDeep)) {
                            scopeDeep[deep] = [];
                        } else {
                            scopeDeep[deep] = {};
                        }
                    }

                    scopeDeep = scopeDeep[deep];
                }

            });
        }

        if (item.hasAttribute('data-editor-type')) {
            _result['editor_type'] = item.getAttribute('data-editor-type');
        }

    });

    // Ранее загруженные — те, которые остались
    let files_to_edit = _form.querySelectorAll(
        '.brf_edit_uploads [' + realcommenter_get_selector('image_gallery_initer_attr') + ']._marked_to_del,.brf_edit_uploads [data-file-id]._marked_to_del'
    );
    if (files_to_edit.length) {

        _result['UF_UPLOADED_TO_DEL'] = [];

        files_to_edit.forEach(function (item) {
            let file_id = (item.hasAttribute(realcommenter_get_selector('image_gallery_initer_attr'))
                    ? item.getAttribute(realcommenter_get_selector('image_gallery_initer_attr'))
                    : item.getAttribute('data-file-id')
            );

            _result['UF_UPLOADED_TO_DEL'].push(file_id);
        });
    }

    // Подгруженные файлы
    let files = _form.querySelectorAll(realcommenter_get_selector('form_files'));

    if (files.length) {
        _result['UF_UPLOADS'] = [];

        files.forEach(function (item) {
            _result['UF_UPLOADS'].push(item.value);
        });
    }

    // recaptcha2
    let recaptcha2_widget = _form.querySelector('.recaptcha2');
    if (recaptcha2_widget) {

        if (
            recaptcha2_widget.hasAttribute('data-inited')
            && recaptcha2_widget.hasAttribute('data-recaptcha2-widget-id')
        ) {

            let widget_id = +recaptcha2_widget.getAttribute('data-recaptcha2-widget-id');
            let widget_response = window['grecaptcha'].getResponse(widget_id);

            if (widget_response) {
                _result['RECAPTCHA2_RESPONSE'] = widget_response;
            }

        }

    }

    // recaptcha3
    if (BX.message['RECAPTCHA3_TOKEN']) {
        _result['RECAPTCHA3_TOKEN'] = BX.message['RECAPTCHA3_TOKEN'];
    }

    return _result;

}

function realcommenter_form_valid(_form) {

    if (!_form) {
        return false;
    }

    realcommenter_find_and_destroy_error_blocks_inside(_form);

    let _errors = [];

    // Поля ввода
    let inputs = _form.querySelectorAll(
        realcommenter_get_selector('form_inputs')
        + realcommenter_get_selector('input_required')
    );

    inputs.forEach(function (item) {

        /**
         * Ситуация:
         * визуальный редактор Битрикса, ввели что-то внутрь и сразу нажали отправить комментарий.
         *
         * Визуальный редактор не успевает выбросить наружу текст и валидатор говорит: нет значения,
         * ...хотя оно фактически внесено
         */

        let _value = '';

        if (~item.id.indexOf('RCM_EDITOR')) {
            _value = window[item.id].GetEditorContent();
        } else if (item.value) {
            _value = item.value;
        }

        if (!_value) {

            _errors.push(item);
            item.classList.toggle('_error', true);

        } else {

            let _data_input = item.getAttribute('data-input');

            if (_data_input && ~_data_input.toLowerCase().indexOf('email')) {

                if (!_value.match(/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/)) {
                    _errors.push(item);
                    item.classList.toggle('_error', true);
                }

            }
        }

    });

    // recaptcha2
    let recaptcha2_widget = _form.querySelector('.recaptcha2');
    if (recaptcha2_widget) {

        recaptcha2_widget.classList.toggle('recaptcha_error', false);
        let recaptcha2_has_error = false;

        if (
            !recaptcha2_widget.hasAttribute('data-inited')
            || !recaptcha2_widget.hasAttribute('data-recaptcha2-widget-id')
        ) {

            recaptcha2_has_error = true;

        } else {
            let widget_id = +recaptcha2_widget.getAttribute('data-recaptcha2-widget-id');
            let widget_response = window['grecaptcha'].getResponse(widget_id);

            if (!widget_response) {
                recaptcha2_has_error = true;
            }

        }

        if (recaptcha2_has_error) {
            _errors.push(recaptcha2_widget);
            recaptcha2_widget.classList.toggle('recaptcha_error', true);
        }
    }

    if (_errors.length) {

        let submit_area = _form.querySelector(realcommenter_get_selector('submit_block'));
        if (submit_area) {

            let more_case = realcommenterNumLang(_errors.length);
            let _error_msg =
                BX.message('FORM_REQUIRED_INPUTS_MSG')
                + _errors.length
                + BX.message('FORM_REQUIRED_INPUTS_CASE_' + more_case);

            realcommenter_form_notice_from_object({
                message: _error_msg
            }, submit_area);
        }

        return false;
    }

    return true;

}

function realcommenter_form_find_and_destroy(obj, css_selector) {

    if (!css_selector || !obj) {
        return;
    }

    let _list = obj.querySelectorAll(css_selector);
    _list.forEach(function (item) {
        item.parentNode.removeChild(item);
    });

}

function realcommenter_form_find_and_turn_off(obj, css_selector, className) {
    if (
        typeof obj === 'undefined' || !obj
        || typeof css_selector === 'undefined' || !css_selector
        || typeof className === 'undefined' || !className
    ) {
        return;
    }

    let _list = obj.querySelectorAll(css_selector);
    _list.forEach(function (item) {
        item.classList.toggle(className, false);
    });

}

/**
 * TODO: memorizer
 */
function realcommenter_form_memorizer() {
    //this - наше поле ввода
}

function realcommenter_form_close(_form) {
    // this - кнопка закрытия

    if (
        typeof this === 'undefined' || !this
        || typeof _form === 'undefined' || !_form
    ) {
        return;
    }

    // Снимаем с комментария отметку про форму внутри
    let comment_obj = _form.closest(realcommenter_get_selector('comment'));
    if (comment_obj) {
        comment_obj.classList.toggle('_incomment', false);
    }

    /**
     * Если мы воткнули форму в нулевой уровень (за границами дерева),
     * мы можем просто её удалить.
     *
     * Иначе мы должна находиться в контейнере с классом ._tmp_for_form
     * Такой случай -- приоритет, удаляем его либо просто форму
     */

    let _tmp_parent = _form.closest(realcommenter_get_selector('form_tmp_wrapper'));
    if (_tmp_parent) {
        _tmp_parent.parentNode.removeChild(_tmp_parent);
    } else {
        _form.parentNode.removeChild(_form);
    }

}

function realcommenter_form_closer_ping(ping_options) {

    let form_obj = document.querySelector(
        '[data-talk-id="' + ping_options['talk_id'] + '"]' + ' '
        + realcommenter_get_selector('form')
        + '[' + realcommenter_get_selector('form_attribute_target') + '=' + ping_options['target_position'] + ']'
    );

    if (!form_obj) {
        return;
    }

    let closer_obj = form_obj.querySelector(realcommenter_get_selector('form_closer'));
    if (!closer_obj) {
        return;
    }

    realcommenter_form_close.bind(closer_obj, form_obj)();

}

Youez - 2016 - github.com/yon3zu
LinuXploit