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 : |
'use strict'; /** * Модуль "Полноценные Комментарии D7" под Битрикс * Официальный сайт модуля: www.realcommenter.com * Официальный сайт разработчика: burlaka.studio * Автор и разработчик: Алексей Бурлака (AlexeyGfi) -> alexeygfi@gmail.com */ function realcommenterNumLang (num) { if (!num || !isFinite(num) || !parseInt(num)) { return 0; } num = num.toString(); if (!num) { return 0; } let last, lastTwo; last = num.substr(-1, 1); if (num.length >= 2) { lastTwo = num.substr(-2, 2); } else { lastTwo = last; } if (last === '1' && lastTwo !== '11') { return 1; } else if ( (last === '2' || last === '3' || last === '4') && (lastTwo !== '12' && lastTwo !== '13' && lastTwo !== '14') ) { return 2; } else { return 3; } } function realcommenter_get_selector (lookingFor) { let selectors = { tree: '.burlakastudio_realcommenter', nav: '.br_nav', body: '.br_tree', comment: '.br_comment', comment_id: '#answercontainer_', expand_button: '.brn_add ins strong', subnode: '.br_node', add_node: '.brn_add', response_links: '.brn_add span', response_textarea: '.brn_add .brna_form._ambushed', response_to_autoreambush: '[data-auto-reambush]', edit_links: '.brn_add abbr', form: '.brna_form', form_editor_area: '.brfb_msg', form_has_errors: '_error_onboard', form_error_area_classname: 'brf_errors', form_attribute_to: 'data-form-to', form_attribute_target: 'data-form-target', form_closer: '.brf_header del', form_inputs: '[data-input]', input_required: '[data-require]', upload_picker: '.brf_submit ins', form_files: 'input[id^="file-doc"]', submit_block: '.brf_submit', form_tmp_wrapper: '._tmp_for_form', form_auth: '.bf_auth', form_auth_form: '.bfa_form', admin_tools: '.brc_header aside > del', admin_fly_cloud: '.br_options', voteblock: '.brc_voteblock', vote_btn: '.br_iva_btn', image_gallery_initer_attr: BX['message']['custom_gallery_image_data_attribute'], image_gallery_initer: '[' + BX['message']['custom_gallery_image_data_attribute'] + ']', sort_and_filter: '.itape_sort_and_filter[data-type]' }; if (lookingFor && selectors[lookingFor]) { return selectors[lookingFor]; } return ''; } /** * Когда мы создаём , нам нужно без точки */ function realcommenter_get_selector_simple (looking_for) { let css_selector = realcommenter_get_selector(looking_for); if (css_selector) { css_selector = css_selector.replace(/\./g, ''); } return css_selector; } function realcommenter_get_jscss_url (jsСssLabel) { if (!jsСssLabel) { return ''; } let jsUrl = BX.message[jsСssLabel]; if (jsUrl) { return jsUrl; } return realcommenter_js_aliases(jsСssLabel); } function realcommenter_js_aliases (js_label) { let js_aliases = { 'le_dialogs.js': '/bitrix/js/fileman/light_editor/le_dialogs.js', 'talk_editor_toolbar_buttons.js': '/bitrix/js/burlakastudio.realcommenter/talk_editor_toolbar_buttons.js', 'le_core.js': '/bitrix/js/fileman/light_editor/le_core.js', 'le_controls.js': '/bitrix/js/fileman/light_editor/le_controls.js', 'talk_editor_controls.js': '/bitrix/js/burlakastudio.realcommenter/talk_editor_controls.js', 'drag_n_drop.js': '/bitrix/js/burlakastudio.realcommenter/drag_n_drop.js', 'talk_gallery.js': '/bitrix/js/burlakastudio.realcommenter/talk_gallery.js', 'browser_hash.js': '/bitrix/js/burlakastudio.realcommenter/browser_hash.js', 'drag_and_fire.js': '/bitrix/js/burlakastudio.realcommenter/drag_and_fire.js' }; return js_aliases[js_label]; } function realcommenter_get_closest_tree (obj) { if (typeof obj === 'undefined' || !obj) { return false; } return obj.closest(realcommenter_get_selector('tree')); } function realcommenter_get_closest_comment (obj) { if (typeof obj === 'undefined' || !obj) { return false; } return obj.closest(realcommenter_get_selector('comment')); } function realcommenter_drag_n_drop_init_JS (callback) { /** * Мы в php пробрасываем время изменения файла. * Если его нет - берём рандом */ BX.loadScript( realcommenter_get_jscss_url('drag_n_drop.js'), callback ); } /** * Эта функция вызывается как при загрузке, * так и при каком-либо обновлении в структуре дерева * * Нам могут через объект события пробросить конкретный DOM-узел, * внутри которого было обновление (чтобы мы не сканировали всё дерево) * * @param evt */ function realcommenter_init_tools (evt) { let scan_in = document; if ( typeof evt !== 'undefined' && evt instanceof CustomEvent ) { evt.preventDefault(); if (evt['detail']) { scan_in = evt['detail']; } } // Кнопки навигации realcommenter_init_nav_buttons(scan_in); // Кнопки "Развернуть" realcommenter_init_expand_buttons(scan_in); // Кнопки "Комментировать" realcommenter_init_response_links(scan_in); // "Высокие" блоки realcommenter_tall_height_scan(scan_in); // Голосование realcommenter_voting(scan_in); // Автораскрытие форм realcommenterFormAutoReambush(); } window.addEventListener('load', realcommenter_init_tools); document.addEventListener('tree_updated', realcommenter_init_tools); function realcommenter_init_nav_buttons (scan_in) { if (typeof scan_in === 'undefined' || !scan_in) { scan_in = document; } let buttons = scan_in.querySelectorAll( realcommenter_get_selector('body') + ' ' + realcommenter_get_selector('nav') + '> *:not(._active):not([data-inited])' ); buttons.forEach(function (item) { item.setAttribute('data-inited', '1'); item.addEventListener('click', realcommenter_pagenav_ipage); }); } function realcommenter_init_expand_buttons (scan_in) { if (typeof scan_in === 'undefined' || !scan_in) { scan_in = document; } let buttons = scan_in.querySelectorAll( realcommenter_get_selector('comment') + ' ' + realcommenter_get_selector('expand_button') + ':not([data-inited])' ); buttons.forEach(function (item) { item.setAttribute('data-inited', '1'); item.addEventListener('click', realcommenter_expand_branch); }); } function realcommenter_init_response_links (scan_in) { if (typeof scan_in === 'undefined' || !scan_in) { scan_in = document; } let links = scan_in.querySelectorAll( realcommenter_get_selector('tree') + ' ' + realcommenter_get_selector('response_links') + ':not([data-inited])' //ещё добавляем нулевые формы комментирования, если они в виде полей ввода + ', ' + realcommenter_get_selector('tree') + ' ' + realcommenter_get_selector('response_textarea') + ':not([data-inited])' //ещё добавляем ссылки на редактирование + ', ' + realcommenter_get_selector('tree') + ' ' + realcommenter_get_selector('edit_links') + ':not([data-inited])' ); links.forEach(function (item) { item.setAttribute('data-inited', '1'); item.addEventListener('click', realcommenter_form_pull); }); } function realcommenter_tall_height_scan (scan_in) { if (!scan_in || scan_in instanceof Event) { scan_in = document; } let articles = scan_in.querySelectorAll( realcommenter_get_selector('comment') + ' > article' + ', ' + realcommenter_get_selector('comment') + ' > .schema_org_wrapper > article' ); articles.forEach(function (item) { /** * 10 - страховка. * Может быть ситуация, когда текст оканчивается на ссылку и * получается: * scrollHeight - 51 * clientHeight - 50 * ...и срабатывает наше условие, а не должно */ if (item.scrollHeight - 10 > item.clientHeight) { item.classList.toggle('_tint_height', true); let toggle_obj = item.querySelector('* > ins.toggle_out'); if (!toggle_obj) { toggle_obj = document.createElement('ins'); toggle_obj.className = 'toggle_out'; item.appendChild(toggle_obj); toggle_obj.addEventListener('click', function () { this.classList.toggle('_tint_height', false); this.classList.toggle('_any_height', true); setTimeout(function () { this.style.maxHeight = '100%'; }.bind(this), 350); }.bind(item)); } } }); } window.addEventListener('resize', realcommenter_tall_height_scan); /** * Добавлен новый комментарий, result[ 'RESULT' ] содержит его id * Пользователь, всё-равно где находится (постраничка, подгрузка порциями, вверху, внизу) * ...должен увидеть свой комментарий. * * Две ситуации: * - это комментарий в нулевой уровень * - ...верхняя форма * - ...нижняя форма * - это ответ на другой комментарий * * Воспользуемся механизмом expand-а комментария, он как раз нам подходит. * • создаём контейнер для отображения комментария; * • пинаем подгрузку; * • скроллим к нему. */ function realcommenter_show_added_comment (id, talk_id, target_position) { if (!id || !talk_id || !target_position) { return false; } let body_obj = realcommenter_get_treebody(talk_id); if (!body_obj) { return false; } /* * <div class="br_comment " id="answercontainer_11"><input type="hidden"></div> * */ let className = realcommenter_get_selector('comment'); className = className.replace(/\./g, ''); /** * 1. Попадает после навигационной цепочки. * Нужно пофиксить * * 2. Если был оставлен комментарий в верхней форме - значит постим в начало дерева * ...иначе — в конец */ let new_obj = document.createElement('div'); new_obj.className = className; new_obj.id = 'answercontainer_' + id; new_obj.innerHTML = ''; if (isFinite(target_position)) { /** * Нужно найти контейнер комментария, на который мы получили ответ */ let target_comment = body_obj.querySelector( realcommenter_get_selector('comment') + realcommenter_get_selector('comment_id') + target_position ); if (target_comment) { target_comment.appendChild(new_obj); let any_child = target_comment.querySelector('*:first-child'); if (any_child) { realcommenter_expand_branch.bind(any_child, { scroll_to_comment: id })(); } } } else { if (target_position === 'bottom') { /** * Если есть навигационная цепочка - публикуем перед ней. Иначе аттачим в конец блока */ let nav_obj = body_obj.querySelector( realcommenter_get_selector('comment') + ' + ' + realcommenter_get_selector('nav') ); if (nav_obj) { body_obj.insertBefore(new_obj, nav_obj); } else { body_obj.appendChild(new_obj); } } else { let first_comment = body_obj.querySelector(realcommenter_get_selector('comment')); if (first_comment) { body_obj.insertBefore(new_obj, first_comment); } else { body_obj.appendChild(new_obj); } } let input_obj = document.createElement('input'); input_obj.type = 'hidden'; new_obj.appendChild(input_obj); realcommenter_expand_branch.bind(input_obj, { scroll_to_comment: id })(); } } function realcommenter_tool_scrollTo (obj, forceShift, onlyIfOutOfView) { if (!obj) { return false; } if (typeof onlyIfOutOfView === 'undefined') { onlyIfOutOfView = false; } if (onlyIfOutOfView && realcommenter_on_view(obj)) { return true; } let box = obj.getBoundingClientRect(); let scrollTo = box.top + pageYOffset + realcommenterGetForced(forceShift); realcommenterSmoothVerticalScrolling(scrollTo); // window.scrollTo({ // top: box.top + pageYOffset + realcommenterGetForced(forceShift), // behavior: 'smooth' // }); } function realcommenterGetForced (forceShift) { if (forceShift) { forceShift = +forceShift; } if (!forceShift || isNaN(forceShift)) { forceShift = -80; } return forceShift; } function realcommenterSmoothVerticalScrolling (scrollTo, callback) { let currentY = realcommenterSmoothVerticalGetCurrentTop(); if (!callback) { callback = false; } let between = Math.abs(Math.abs(currentY) - Math.abs(scrollTo)); if ( between > 5 // we may scrolling down more && (document.body.scrollHeight - (currentY + window.innerHeight) > 10) ) { let newShift = (between / 4) * (currentY > scrollTo ? -1 : 1); let newStep = currentY + newShift; window.scrollTo(0, newStep); setTimeout(realcommenterSmoothVerticalScrolling, 25, scrollTo, callback); } else { window.scrollTo(0, scrollTo); if (callback) { callback(); } } } function realcommenterSmoothVerticalGetCurrentTop () { return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop; } /** * 1. Ситуация с подскролами * * Одна сторона медали: есть комментарий, под которым уже внушительное ветвление. * Оставляем комментарий по ссылке "Ответить" и он появляется где-то далеко внизу. * * Другая сторона медали: оставляем комментарий в небольшой веточке, где "всё перед глазами". * Если мы оставляем комментарий, достаточно чтобы он просто появился перед глазами. * Подскролл в этом случае будет просто бесить. * * ...то есть всегда подскроливать — не верно. Нужно подскроливать тогда, когда комментарий * не появляется в области видимости (за экраном) * * 2. Подсвечивать. (???) Достаточно ли просто синей точки? * */ function realcommenter_on_view (obj) { // https://prnt.sc/o6ui7r let box = obj.getBoundingClientRect(); if (box.y < 0 || box.y > window.innerHeight) { return false; } else { return true; } } /** * Запрашиваем развёрнутую ветку под текущим комментарием * * Нам нужно передать: * - код обсуждения * - код комментария, под которым разворачиваем ветку */ function realcommenter_expand_branch (append_data) { //this - наша кнопка. 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; } let _data = { request_type: 'expand', comment_id: comment_id_matches.shift() }; /** * Пример объекта, который может быть передан: * { scroll_to_new_comment: 1 } */ if (append_data && append_data instanceof Object) { for (let a in append_data) { if (!append_data.hasOwnProperty(a)) { continue; } _data[a] = append_data[a]; } } realcommenter_ajaxion.bind(this, { url: '/bitrix/admin/burlakastudio.realcommenter.talk_tree.php', onsuccess: realcommenter_place_node, data: _data })(); } function realcommenter_get_talk_by_id (talk_id) { if (typeof talk_id === 'undefined' || !talk_id) { return false; } return document.querySelector( realcommenter_get_selector('tree') + '[data-talk-id="' + talk_id + '"]' ); } /** * Ищем непосредственно узел тела дерева обсуждения * * Нам могут передать как talk_id (ищем по селектору .br_tree#itape_1 ) * ...так и контейнер обсуждения (ищем по селектору .br_tree) * */ function realcommenter_get_treebody (talk_id, talk_obj) { if ( (typeof talk_id === 'undefined' || !talk_id) && (typeof talk_obj === 'undefined' || !talk_obj) ) { return false; } if (talk_id) { return document.querySelector( realcommenter_get_selector('body') + '#itape_' + talk_id ); } return talk_obj.querySelector(realcommenter_get_selector('body')); } function realcommenter_place_node (result) { if (typeof result['ERROR'] !== 'undefined' && Object.keys(result['ERROR']).length) { console.log('ERROR'); console.log(result); return; } if (result['HTML'] !== 'undefined' && result['HTML']) { let comment_id = result['request']['comment_id']; let talk_obj = realcommenter_get_talk_by_id(result['request']['talk_id']); if (talk_obj) { let comment_row_obj = talk_obj.querySelector( realcommenter_get_selector('comment') + '[id="answercontainer_' + comment_id + '"]' ); if (comment_row_obj) { //!) Нужно получить до замены html-текста let comment_parent = comment_row_obj.parentNode; comment_row_obj.outerHTML = result['HTML']; let event = new CustomEvent('tree_updated', { bubbles: true, cancelable: true, detail: comment_parent } ); document.dispatchEvent(event); /** * Либо нам в запросе пробросили код комментария, к которому подскроллить, * либо скролим к комментарию, с которым производились действий. * * Это не всегда одно и то же. * Например, новый комментарий (пробрасываем отдельно) находится ВНУТРИ ветки, * которую разворачиваем (с которой фактически работаем) */ let comment_obj; if (result['request']['scroll_to_comment']) { comment_obj = comment_parent.querySelector( realcommenter_get_selector('comment_id') + result['request']['scroll_to_comment'] ); if (comment_obj) { /** * Подсветим */ comment_obj.classList.toggle('_hightlight', true); setTimeout(function () { this.classList.toggle('_hightlight', false); }.bind(comment_obj), 3000); } } if (!comment_obj) { comment_obj = comment_parent.querySelector( realcommenter_get_selector('comment_id') + result['request']['comment_id'] ); } /** * 1. Ситуация с подскролами * * Одна сторона медали: есть комментарий, под которым уже внушительное ветвление. * Оставляем комментарий по ссылке "Ответить" и он появляется где-то далеко внизу. * * Другая сторона медали: оставляем комментарий в небольшой веточке, где "всё перед глазами". * Если мы оставляем комментарий, достаточно чтобы он просто появился перед глазами. * Подскролл в этом случае будет просто бесить. * * ...то есть всегда подскроливать — не верно. Нужно подскроливать тогда, когда комментарий * не появляется в области видимости (за экраном) * * 2. Подсвечивать. (???) Достаточно ли просто синей точки? * */ realcommenter_tool_scrollTo(comment_obj, -100, true); } } } } /** * Пробрасываем через себя все запросы. * Внутри общая для всех запросов инициализация, потому стандартизируем * * ajax_options - объект. * Обязательные ключи: * url - вызываемый урл * onsuccess - колбэк * * Необязательные ключи: * data - объект, который будет доклеен до data аякса * dataType - тип ожидаемого ответа * * @param ajax_options * @returns {boolean} */ function realcommenter_ajaxion (ajax_options) { if ( typeof ajax_options === 'undefined' || !ajax_options || !ajax_options['url'] || !ajax_options['onsuccess'] || !(ajax_options['onsuccess'] instanceof Function) ) { return false; } let _talk; // this должен быть определён элементом, но мы страхуемся на тот случай, если нет if (this === window) { _talk = document.querySelector(realcommenter_get_selector('tree')); } else { _talk = this.closest(realcommenter_get_selector('tree')); } if (!_talk) { return false; } let _data = { //request_type: action, talk_id: _talk.getAttribute('data-talk-id'), talk_url: _talk.getAttribute('data-talk-url'), talk_hash: _talk.getAttribute('data-talk-hash'), LANGUAGE_ID: BX.message('LANGUAGE_ID'), SITE_ID: BX.message('SITE_ID') }; let outside_var = _talk.querySelector('[data-outside-var]'); if (outside_var) { _data['outside_var'] = outside_var.getAttribute('data-outside-var'); } let admin_keys = _talk.querySelector('[data-admin-keys]'); if (admin_keys) { _data['admin_keys'] = admin_keys.getAttribute('data-admin-keys'); } let tape_variables = document.querySelector('input[type="hidden"][data-realcommenter-tape-variables]'); if (tape_variables) { _data['tape_variables'] = tape_variables.getAttribute('data-realcommenter-tape-variables'); } if (ajax_options['data']) { for (let d in ajax_options['data']) { if (!ajax_options['data'].hasOwnProperty(d)) { continue; } _data[d] = ajax_options['data'][d]; } } /** * Нам не угадать: элемент может быть очень маленьким. * Затемняем его родителя */ let parent_comment = null; if (typeof this.closest !== 'undefined' && this.closest instanceof Function) { parent_comment = this.closest(realcommenter_get_selector('comment')); if (!parent_comment) { parent_comment = this.closest(realcommenter_get_selector('body')); if (!parent_comment) { parent_comment = _talk; } } } else { parent_comment = _talk; } if (parent_comment) { realcommenter_tint_area(1, parent_comment); } BX.ajax({ url: ajax_options['url'], data: _data, dataType: (ajax_options['dataType']) ? ajax_options['dataType'] : 'json', method: (ajax_options['method']) ? ajax_options['method'] : 'POST', onsuccess: realcommenter_ajaxed_success.bind(ajax_options['onsuccess']), onfailure: function () { console.log('error'); } }); } function realcommenter_ajaxed_success (result) { // this - наш колбэк realcommenter_tint_area(0); /** * В качестве альтернативной возможности предусмотрен смешанный вариант ответа. * То есть html__**||**__json * * Если нам в ответ пришёл html * и в нём встречается такой разделитель, мы его режем, json парсим и переопределяем result */ if (typeof result === 'string') { if (~result.indexOf('__**||**__')) { let result_parts = result.split('__**||**__'); result = JSON.parse(result_parts[1]); result['HTML'] = result_parts[0]; } } /** * Стандартное поле в ответе: BX_MSG - массив, которым добиваем лингвистические фразы BX.message * ! typeof null == 'object' */ if (typeof result === 'object' && typeof result['BX_MSG'] === 'object' && result['BX_MSG'] && Object.keys(result['BX_MSG']).length) { for (let mk in result['BX_MSG']) { if (!result['BX_MSG'].hasOwnProperty(mk)) { continue; } BX.message[mk] = result['BX_MSG'][mk]; } } if (typeof this !== 'undefined' && this instanceof Function) { this(result); } } function realcommenter_tint_area (mode, node_or_css_selector, additional_css, init_timeout) { /** * Нам нужен таймер, чтобы если операция через аякс отработает быстро, можно было прервать затемнение */ clearTimeout(window.realcommenter_tint_timer); /** * Сохраняем возможность: * передать mode == 1 и (селектор или объект) * передать mode == 0 и пустой селектор/объект — чтобы чистить подсветку */ if (typeof mode === 'undefined') { mode = 0; } let all_markers = document.querySelectorAll('.ncli_tinter'); if (all_markers && all_markers.length) { all_markers.forEach(function (item) { item.parentNode.removeChild(item); }); } if (mode) { if (typeof node_or_css_selector === 'undefined' || !node_or_css_selector) { return; } if (typeof additional_css === 'undefined') { additional_css = ''; } if (typeof init_timeout === 'undefined') { init_timeout = 1000; } //Запускаем не сразу, потому что моргает мерзко window.realcommenter_tint_timer = setTimeout(realcommenter_tint_process.bind(this, node_or_css_selector, additional_css), init_timeout); } } function realcommenter_tint_process (node_or_css_selector, additional_css) { clearTimeout(window.realcommenter_tint_timer); if (typeof node_or_css_selector === 'undefined' || !node_or_css_selector) { return; } if (typeof additional_css === 'undefined') { additional_css = ''; } let _obj; if (typeof node_or_css_selector === 'string') { _obj = document.querySelector(node_or_css_selector); } else { //! нам могут пробросить и объект _obj = node_or_css_selector; } if (!_obj) { return; } let i = document.createElement('i'); i.className = 'ncli_tinter ' + additional_css; _obj.appendChild(i); } function realcommenter_pagenav_ipage (e) { //this - наша кнопка. if (e) { if (e.preventDefault) { e.preventDefault(); // Cancel the native event } if (e.stopPropagation) { e.stopPropagation(); } } let ipage = 1; let isort = ''; let navAction = ''; let crossingOptions = {}; if (this && this.getAttribute) { if (this.hasAttribute('data-ipage')) { ipage = this.getAttribute('data-ipage'); } if (this.hasAttribute('data-isort')) { // force from data-attribute isort = this.getAttribute('data-isort'); } if (this.hasAttribute('data-nav-action')) { // force from data-attribute navAction = this.getAttribute('data-nav-action'); } if (this.ajaxCrossOptions) { crossingOptions = Object.assign(crossingOptions, this.ajaxCrossOptions); } } if (!isort) { // ...or try to get from url (default) let queryString = window.location.search; let urlParams = new URLSearchParams(queryString); isort = urlParams.get('isort'); } realcommenter_ajaxion.bind(this, { url: '/bitrix/admin/burlakastudio.realcommenter.talk_tree.php', onsuccess: realcommenter_pagenav_process, data: { request_type: 'pagenav', ipage: parseInt(ipage), isort: isort, nav_action: navAction, crossOption: crossingOptions }, })(); return false; } function realcommenterSortPull (sort) { let tree = document.querySelector(realcommenter_get_selector('tree')); if (!tree) { return; } let operateWith = tree.children[0]; if (sort) { operateWith.setAttribute('data-isort', sort); } else { operateWith.removeAttribute('data-isort'); // url should be clear of isort if (window.location.search.match(/isort=[a-z\-]+/)) { let talkObj = document.querySelector(realcommenter_get_selector('tree')); if (talkObj) { realcommenterHistoryPush(talkObj, true); } } } operateWith.ajaxCrossOptions = { skipAfterscroll: 1, skipAppendMode: 1 }; realcommenter_pagenav_ipage.call(operateWith); } function realcommenter_pagenav_process (result) { if (typeof result['ERROR'] !== 'undefined' && Object.keys(result['ERROR']).length) { console.log('ERROR'); console.log(result); return; } if (result['HTML'] !== 'undefined' && result['HTML']) { let talkObj = realcommenter_get_talk_by_id(result['request']['talk_id']); if (talkObj) { let bodyObj = realcommenter_get_treebody('', talkObj); if (bodyObj) { /** * Если обычная постраничка - заменяем тело. * * Если подгрузка порциями ( result[ 'NAV_APPEND' ] ) * ... Удаляем что есть навигационное и аппендим к дереву то, что пришло */ let skipAppendModeByIsort = ( result['request']['crossOption'] && result['request']['crossOption']['skipAppendMode'] ); if (!skipAppendModeByIsort && result['NAV_APPEND'] !== 'undefined' && result['NAV_APPEND']) { let navParts = bodyObj.querySelectorAll( realcommenter_get_selector('nav') ); navParts.forEach(function (item) { item.parentNode.removeChild(item); }); /** * Пробрасываем грамотно, * чтобы не нарушить уже прописанные собутия выше по ветке */ let tonnelObj = document.createElement('div'); tonnelObj.style.display = 'none'; tonnelObj.innerHTML = result['HTML']; bodyObj.appendChild(tonnelObj); while (tonnelObj.children.length) { bodyObj.appendChild(tonnelObj.children[0]); } tonnelObj.parentNode.removeChild(tonnelObj); } else { bodyObj.innerHTML = result['HTML']; let ipage = result['request']['ipage'] ? +result['request']['ipage'] : 1; let isort = result['request']['isort'] ? result['request']['isort'] : ''; realcommenterHistoryPush(talkObj, ipage, isort); /** * Так как мы заменили тело полностью, нужно подскроллить к началу дерева */ if (!result['request']['crossOption'] || !result['request']['crossOption']['skipAfterscroll']) { let safContainer = document.querySelector( realcommenter_get_selector('tree') + ' ' + realcommenter_get_selector('sort_and_filter') ); if (safContainer) { realcommenter_tool_scrollTo(safContainer); } else { realcommenter_tool_scrollTo(bodyObj); } } } let event = new CustomEvent('tree_updated', { bubbles: true, cancelable: true, detail: bodyObj } ); document.dispatchEvent(event); } } } } function realcommenterHistoryPush (talkObj, ipage, isort) { /** * Пушим в историю браузера урл */ let basePath = talkObj.getAttribute('data-talk-url'); let urlArguments = []; if (ipage && !isNaN(ipage) && ipage !== 1) { // We should preserve ipage from url if exists if (ipage === true) { let ipageInUrl = window.location.search.match(/ipage=([a-z]+)/); if (ipageInUrl) { ipage = ipageInUrl[1]; } else { ipage = null; } } if (ipage && !isNaN(ipage) && ipage !== 1) { urlArguments.push(`ipage=${ipage}`); } } if (isort) { urlArguments.push(`isort=${isort}`); } let historyUrl = basePath + (urlArguments.length ? '?' + urlArguments.join('&') : ''); history.pushState(null, '', historyUrl); } function realcommenter_voting (scan_in) { if (!scan_in || scan_in instanceof Event) { scan_in = document; } let vote_blocks = scan_in.querySelectorAll(realcommenter_get_selector('voteblock') + ':not(._used):not([data-inited])'); vote_blocks.forEach(function (item) { let comment_id = +item.id.replace(/[^0-9]/g, ''); if (!comment_id) { return; } let voting = item.querySelectorAll(realcommenter_get_selector('vote_btn')); voting.forEach(function (btn) { btn.addEventListener('click', realcommenter_vote_cpu.bind(btn, comment_id)); }); item.setAttribute('data-inited', '1'); }); } /** * Подскролл к найденному элементу. * "Найденный" - тот, чей код задан в урле в ключе itape * ...но нам урл отслеживать не нужно. * На страницу уже приходит его интерпретация, с наличием в классах _found */ function realcommenterScrollToFound () { let obj = document.querySelector('._found:not([data-scrolled])'); if (!obj) { return; } /** * Чтобы не случилось такого, что снова сработало событие, * ...и нас снова добросило до этого выделенного элемента */ obj.setAttribute('data-scrolled', '1'); // ...чтобы по центру устройства оказался элемент realcommenter_tool_scrollTo(obj, -1 * window.innerHeight / 2); setTimeout(function () { this.classList.toggle('_found_and_faded', 1); }.bind(obj), 2000); } window.addEventListener('DOMContentLoaded', function () { setTimeout(realcommenterScrollToFound, 1000); }); function realcommenter_vote_cpu (comment_id) { //this - стрелка голосования if (!this || !comment_id) { return; } let vote_weight = ~this.className.indexOf('_up') ? 1 : -1; let _data = { request_type: 'voting', comment_id: comment_id, vote_weight: vote_weight }; realcommenter_ajaxion.bind(this, { url: '/bitrix/admin/burlakastudio.realcommenter.talk_tree.php', onsuccess: realcommenter_voting_done, data: _data })(); } function realcommenter_voting_done (result) { if (typeof result['ERROR'] !== 'undefined' && Object.keys(result['ERROR']).length) { console.log('ERROR'); console.log(result); return; } if (result['VOTEBLOCK_RESULT'] !== 'undefined' && result['VOTEBLOCK_RESULT']) { let comment_id = +result['request']['comment_id']; if (comment_id) { let voteblock = document.querySelector(realcommenter_get_selector('voteblock') + '#ivt_' + comment_id); if (voteblock) { let aside = voteblock.closest('aside'); if (aside) { aside.outerHTML = result['VOTEBLOCK_RESULT']; } } } } } function realcommenter_auth_init (node2load) { if (!node2load) { return false; } if (typeof node2load === 'string') { node2load = BX(node2load); if (!node2load) { return false; } } BX.loadScript( [ realcommenter_get_jscss_url('talk_auth.js'), realcommenter_get_jscss_url('ss.js'), ], function () { realcommenter_ajaxion.bind(node2load, { url: '/bitrix/admin/burlakastudio.realcommenter.auth_ajax.php', dataType: 'html', onsuccess: realcommenter_auth_ajax_answer.bind(node2load), data: { request_type: 'form' } })(); }); } function realcommenter_auth_ajax_answer (result) { // this - узел, куда поместить html if (!result || !this) { return; } this.innerHTML = result; // Выбрасываем событие на инициализацию формы авторизации let event = new CustomEvent('auth_form_placed', { bubbles: true, cancelable: true } ); document.dispatchEvent(event); } function realcommenter_find_and_destroy_error_blocks_inside (obj) { if (!obj) { return false; } realcommenter_form_find_and_destroy(obj, '.errors'); realcommenter_form_find_and_destroy(obj, '.' + realcommenter_get_selector('form_has_errors')); realcommenter_form_find_and_destroy(obj, '.' + realcommenter_get_selector('form_error_area_classname')); realcommenter_form_find_and_turn_off(obj, '._error', '_error'); } function realcommenter_gallery_scan_and_init () { let img_nodes = document.querySelectorAll( realcommenter_get_selector('image_gallery_initer') + ':not([data-inited])' ); img_nodes.forEach(function (item) { item.addEventListener('click', realcommenter_gallery_load_and_init); item.setAttribute('data-inited', '1'); }); } window.addEventListener('load', realcommenter_gallery_scan_and_init); document.addEventListener('tree_updated', realcommenter_gallery_scan_and_init); function realcommenter_gallery_load_and_init () { //this - span, на который кликнули BX.loadScript( [ realcommenter_get_jscss_url('talk_gallery.js'), realcommenter_get_jscss_url('browser_hash.js'), realcommenter_get_jscss_url('drag_and_fire.js') ], function () { realcommenter_gallery_ping(this); }.bind(this) ); }