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_tree.js
  '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)
  );

}

Youez - 2016 - github.com/yon3zu
LinuXploit