Полный цикл в digital

Получение событий для кастомизации интерфейса Битрикс 24

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

BX.onCustomEvent

Выброс события производится через BX.onCustomEvent и происходит в любом случае, вне зависимости от того, есть ли слушатели события или нет. Для нас — разработчиков — это является информацией о том, в каком месте существуют точки входа, на которые при необходимости можно было бы подписаться и реагировать.

Код для выполнения в консоли:

let originalBxOnCustomEvent = BX.onCustomEvent;
// глобальный объект, в который будет собираться статистика
hardcoreBXOnEventFrontLog = {
  events: {},
};
BX.onCustomEvent = function (objOrEvent, eventIHope, eventParams, secureParams) {
  if (!objOrEvent) {
    objOrEvent = null;
  }
  if (!eventIHope) {
    eventIHope = null;
  }
  if (!eventParams) {
    eventParams = null;
  }
  if (!secureParams) {
    secureParams = null;
  }
  let info = {};
  let realEvent, realObj;
  if (typeof objOrEvent === 'string') {
    realEvent = objOrEvent;
  } else if (typeof eventIHope === 'string') {
    realEvent = eventIHope;
  }
  if (typeof objOrEvent === 'object') {
    realObj = objOrEvent;
  } else if (typeof eventIHope === 'object') {
    realObj = eventIHope;
  } else if (typeof eventParams === 'object') {
    realObj = eventParams;
  }
  let err = new Error();
  info.trace = err.stack;
  info.event = realEvent;
  info.obj = realObj;
  info.params = eventParams;
  info.arguments = arguments;
  // live! =)
  hardcoreBXFrontPrintOnEvent(info, true);
  // регистрируем в глобальном объекте
  let eventNameList = realEvent.split(' ');
  eventNameList.forEach(function (evt) {
    if (!hardcoreBXOnEventFrontLog.events[evt]) {
      hardcoreBXOnEventFrontLog.events[evt] = [];
    }
    hardcoreBXOnEventFrontLog.events[evt].push(info);
  });
  // пинаем оригинальный метод
  return originalBxOnCustomEvent.call(this, objOrEvent, eventIHope, eventParams, secureParams);
};
// метод для поиска среди собранной статистики информации по названию события
hardcoreBXOnEventLookingByEvent = function (event) {
  for (let e in hardcoreBXOnEventFrontLog.events) {
    if (
      !hardcoreBXOnEventFrontLog.events.hasOwnProperty(e)
      || e !== event
    ) {
      continue;
    }
    for (let ins = 0; ins < hardcoreBXOnEventFrontLog.events[e].length; ins++) {
      hardcoreBXFrontPrintOnEvent(hardcoreBXOnEventFrontLog.events[e][ins]);
    }
  }
};
// вывод в консоль
hardcoreBXFrontPrintOnEvent = function (info, live) {
  let localInfo = Object.assign({}, info);
  console.log(
    'BX.on%c%s',
    'background: #fa8544; color: #fff; ' +
    'font-weight: bold; padding: 3px 9px;' +
    'border-radius: 30px 0 0 30px;' +
    'border-left: 7px solid #1d1b57',
    localInfo.event
  );
  if (localInfo.obj) {
    console.log(localInfo.obj);
  }
  console.groupCollapsed('trace');
  if (live) {
    console.trace();
    delete (localInfo.trace);
  } else {
    console.log(localInfo.trace);
  }
  console.groupEnd();
  console.groupCollapsed('info');
  for (let i in localInfo) {
    if (localInfo.hasOwnProperty(i)) {
      console.log(i + ':%o', localInfo[i]);
    }
  }
  console.groupEnd();
};

Статистика

В консоли будет накапливаться информация о каждом событии, которое было проинициализировано через BX.onCustomEvent, с трейсингом вызова, что позволит нам понять, откуда именно это было запущено:

Также вся информация будет накапливаться в глобальный объект hardcoreBXOnEventFrontLog, отсортированная по событиям. К сожалению, полноценный трейсинг в переменную не запомнить, но часть цепочки сохраняется, через объект Error. Это хотя бы частично позволяет сориентироваться в том, откуда пришёл сигнал.

Собранную на текущий момент статистику по событиям получаем через функцию hardcoreBXOnEventLookingByEvent("название_события").

Упрощенный вариант

Код для выполнения в консоли:

let originalBxOnCustomEvent = BX.onCustomEvent;
BX.onCustomEvent = function (eventObject, eventName, eventParams, secureParams)
{
    let realEventName = BX.type.isString(eventName) ?
        eventName : BX.type.isString(eventObject) ? eventObject : null;

    if (realEventName) {
        console.log(
            '%c' + realEventName,
            'background: #222; color: #bada55; font-weight: bold; padding: 3px 4px;'
        );
    }

    console.dir({
        eventObject: eventObject,
        eventParams: eventParams,
        secureParams: secureParams
    });

    originalBxOnCustomEvent.apply(
        null, arguments
    );
};

После чего будут логироваться все события которые вызываются например при клике на кнопку!

Далее вешаем обработчики через:

BX.addCustomEvent()

BX.addCustomEvent

По аналогии с тем, как устроена работа с событиями в jQuery, методы BX-библиотеки являются функциями-аккумуляторами. Подписывание на событие фактически явлется регистрацией символьного кода и колбэк-функции в глобальном объекте, а выброс события — выполнение колбэк-функции.

Регистрация события производится через функцию

BX.addCustomEvent

Как правило регистрацию события сопровождают:

  • Событие в виде произвольного символьного кода click, load, on-location-search-focus
  • Колбэк-функция, которая должна быть вызвана при наступлении события

Как и в случае с jQuery, переопределяем исходный метод и переопределяем его своим.

Переопределение метода

Предлагается сделать следующее:

  1. Ставим в девтулзах глобальный брекпоинт на событие document.onDOMContentLoaded, перезагружаем страницу
  2. На первом срабатывании брекпоинта убеждаемся, что объект BX уже доступен и переопределяем ему метод addCustomEvent
  3. Снимаем брекпоинт и отпускаем выполнение скрипта

Код для выполнения в консоли:

let originalBxAddCustomEvent = BX.addCustomEvent;
// глобальный объект, в который будет собираться статистика
hardcoreBXFrontLog = {
  events: {},
};
/**
 * eventOrObj - example: BX.addCustomEvent(opener, 'onOpenerMenuClose', ...)
 */
BX.addCustomEvent = function (eventOrObj, handlerOrEvent, arParams, handlerContextObject) {
  let info = {};
  let realEvent, realCallback, someObj;
  if (typeof eventOrObj === 'string') {
    realEvent = eventOrObj;
  } else if (typeof handlerOrEvent === 'string') {
    realEvent = handlerOrEvent;
  }
  if (eventOrObj instanceof Function) {
    realCallback = eventOrObj;
  } else if (handlerOrEvent instanceof Function) {
    realCallback = handlerOrEvent;
  } else if (arParams instanceof Function) {
    realCallback = arParams;
  }
  if (typeof eventOrObj === 'object') {
    someObj = eventOrObj;
  } else if (typeof handlerOrEvent === 'object') {
    someObj = handlerOrEvent;
  } else if (typeof arParams === 'object') {
    someObj = arParams;
  }
  let err = new Error();
  info.trace = err.stack;
  info.event = realEvent;
  info.callback = realCallback;
  info.obj = someObj;
  info.arguments = arguments;
  // live! =)
  hardcoreBXFrontPrintResult(info, true);
  // регистрируем в глобальном объекте
  let eventNameList = realEvent.split(' ');
  eventNameList.forEach(function (evt) {
    if (!hardcoreBXFrontLog.events[evt]) {
      hardcoreBXFrontLog.events[evt] = [];
    }
    hardcoreBXFrontLog.events[evt].push(info);
  });
  // пинаем оригинальный метод
  if (!arParams) {
    arParams = [];
  }
  if (!handlerContextObject) {
    handlerContextObject = false;
  }
  return originalBxAddCustomEvent.call(this, eventOrObj, handlerOrEvent, arParams, handlerContextObject);
};
// метод для поиска среди собранной статистики информации по названию события
hardcoreBXAddEventLookingByEvent = function (event) {
  for (let e in hardcoreBXFrontLog.events) {
    if (
      !hardcoreBXFrontLog.events.hasOwnProperty(e)
      || e !== event
    ) {
      continue;
    }
    for (let ins = 0; ins < hardcoreBXFrontLog.events[e].length; ins++) {
      hardcoreBXFrontPrintResult(hardcoreBXFrontLog.events[e][ins]);
    }
  }
};
// вывод в консоль
hardcoreBXFrontPrintResult = function (info, live) {
  let localInfo = Object.assign({}, info);
  console.log(
    'BX.add%c%s',
    'background: #1d1b57; color: #fff; ' +
    'font-weight: bold; padding: 3px 9px;' +
    'border-radius: 0 30px 30px 0;' +
    'border-right: 7px solid #fa8544',
    info.event
  );
  if (localInfo.obj) {
    console.log(localInfo.obj);
  }
  console.groupCollapsed('trace');
  if (live) {
    console.trace();
    delete (localInfo.trace);
  } else {
    console.log(localInfo.trace);
  }
  console.groupEnd();
  console.groupCollapsed('info');
  for (let i in localInfo) {
    if (localInfo.hasOwnProperty(i)) {
      console.log(i + ':%o', localInfo[i]);
    }
  }
  console.groupEnd();
};

Статистика

В консоли будет накапливаться информация о каждом событии, которое было проинициализировано через BX.addCustomEvent, с трейсингом вызова, что позволит нам понять, откуда именно это было запущено:

Также вся информация будет накапливаться в глобальный объект hardcoreBXFrontLog, отсортированная по событиям. К сожалению, полноценный трейсинг в переменную не запомнить, но часть цепочки сохраняется, через объект Error. Это хотя бы частично позволяет сориентироваться в том, откуда пришёл сигнал.

Собранную на текущий момент статистику по событиям получаем через функцию hardcoreBXAddEventLookingByEvent("название_события").

Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг