Замена console.log для кроссбраузерной отладки

в 20:35, , рубрики: javascript, jquery, Веб-разработка, кроссбраузерность, отладка, отладка javascript, метки: , , ,

Отладка — неизбежный и зачастую очень длительный этап разработки любого приложения. Клиентская веб-разработка в этом смысле не исключение, более того, здесь этот вопрос стоит особенно остро. Если при отладке backend’а область действий программиста ограничена инструментом разработки, то в frontend’е задачу отладки осложняют многочисленные внешние факторы — браузеры. С их многообразием и различиями приходится волей-неволей считаться любому веб-разработчику. Об этом и пойдет речь далее.

Данная статья не претендует на оригинальность. Вполне возможно, что что-то подобное уже было написано ранее кем-то другим. Единственной целью при ее написании было желание автора поделиться своим опытом в отладке JavaScript. Автор уважает мнения других хабрапользователей и никому не навязывает свою точку зрения.

Проблема кроссбраузерности в отладке уже неоднократно рассматривалась на Хабре (1, 2, 3 и др.). Но к сожалению, во всех статьях, ранее освещавших этот вопрос, применялся один и тот же подход к его решению: использование инструментов отладки, специфичных для каждого браузера. Конечно, никто еще не отменял console.log — простой, и в некотором смысле кроссбраузерный, инструмент, хорошо помогающий в отладке. Но его применение опять-таки ограничено наличием в браузере средств отладки. Особенно это касается мобильных устройств, в которых получить доступ к средствам отладки не так просто, а иногда и вовсе невозможно.

Я давно уже привык использовать для клиентской отладки Firefox с его замечательным плагином Firebug. И да простят меня сторонники всех остальных браузеров, меня никогда не радовала необходимость разбираться с инструментами отладки в других браузерах. Я был бы рад найти аналог console.log, работающий в любом браузере и не требующий установки и изучения специальных инструментов.

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

Я знаю как это выглядит на первый взгляд. Но не спешите лезть в карман за минусами. Прошу вас прежде дочитать эту статью до конца.

Да, это напоминает отладку в худших традициях PHP-быдлокодерства — вывод через echo/print. Но в отличие от серверной отладки, в frontend’е этим выводом можно управлять с большой гибкостью (так что он не будет разбросан по всей странице в неприглядном виде).

Да, этот способ далеко не идеален. Главный его недостаток состоит в том, что такой отладочный вывод необходимо удалять после окончания проверки (в production-версии разумеется его никак нельзя оставлять). Но вместе с тем, задача очистки кода от отладочного вывода не представляет особой сложности. Это легко можно делать вручную, но лучше все-таки использовать для этого программные средства (скрипты).

В результате этих размышлений мной был написан небольшой код для замены функций console.log. Я называю его по привычке jQuery плагином, хотя по сути это конечно же не так: он ничего не добавляет к функциональности jQuery, хотя и использует его средства. Вот этот код:

if (!window.herelog && window.jQuery) {

window.herelog= {
  oOut: null,
  bOn: false,
  fnAction: null,
  init: function(oParams) {
    if (this.oOut) return;
    var oCfg= {
      oPlace: null,
      bInitOn: true,
      bInitShow: false,
      fnAction: null,
      oLanguage: {title: 'windowlog:',
        on: 'ON', show: 'Show', clear: 'Clear', action: 'Action'
      }
    };
    if (oParams) jQuery.extend(true, oCfg, oParams);
    this.bOn= oCfg.bInitOn;
    this.fnAction= (typeof oCfg.fnAction == 'function')? oCfg.fnAction : null;
    var oCtrl= jQuery(
      '<form class="windowlog-ctrl" onsubmit="return false">'+
      '<h1>'+ oCfg.oLanguage.title+ '</h1>'+
      ' <label><input type="checkbox" class="wl-on"'+
        (this.bOn? ' checked' : '')+ '/>'+ oCfg.oLanguage.on+ '</label>'+
      ' <label><input type="checkbox" class="wl-show"'+
        (oCfg.bInitShow? ' checked' : '')+ '/>'+ oCfg.oLanguage.show+ '</label>'+
      ' <button class="wl-clear">'+ oCfg.oLanguage.clear+ '</button>'+
      (this.fnAction?
      ' <button class="wl-action">'+ oCfg.oLanguage.action+ '</button>' : '')+
      '</form>'
    );
    this.oOut= jQuery(
      '<div class="windowlog-output" style="display:'+
      (oCfg.bInitShow? 'block': 'none')+ '"/>'
    );
    jQuery(oCfg.oPlace? oCfg.oPlace : (document.body? document.body : document))
    .append(oCtrl).append(this.oOut);
    var self= this;
    oCtrl.find('input.wl-on').change(function() {
      self.bOn= !self.bOn;
    });
    oCtrl.find('input.wl-show').change(function() {
      self.oOut.toggle();
    });
    oCtrl.find('button.wl-clear').click(function() {
      self.oOut.html('');
    });
    if (this.fnAction) oCtrl.find('button.wl-action').click(function() {
      self.fnAction.call(this, self.oOut.eq(0));
    });
  },
  add: function(text) {
    if (this.oOut && this.bOn) this.oOut.append('<p>'+ text+'</p>');
  }
};

}

Как видно, jQuery используется только во внутренней реализации плагина, внешний же его интерфейс не зависит от jQuery. Так что содержание плагина может быть переписано под использование только чистого JavaScript’а. Возможно, в будущем я так и сделаю. Пока же он меня вполне устраивает и в таком виде.

Как использовать

Инициализация (настройка):

herelog.init(oSettings); // oSettings - объект настройки.

Добавление информации в отладочный вывод:

herelog.add(text);

Список свойств (параметров) объекта настройки:

Имя свойства Тип Описание
oPlace Object/String DOM элемент (либо определяющий его jQuery-селектор), в котором будет помещаться блок отладочного вывода. В случае отсутствия этого свойства данный блок будет помещен в конце тела текущего документа
bInitOn Boolean Начальное состояние переключателя «On» (включить отладочный вывод).
bInitShow Boolean Начальное состояние переключателя «Show» (показывать отладочную информацию).
fnAction Callback Function Функция обратного вызова, вызываемая для выполнения определенного действия с отладочной информацией.

Расскажу подробнее о функции обратного вызова. Она должна иметь следующий формат:

function (oElem) {...}

где oElem — DOM элемент, соответствующий блоку отладочного вывода.
Какое действие будет выполняться при вызове этой функции — решать вам. На мой взгляд наиболее логичным выглядит отправка через AJAX отладочной информации на сервер разработчика, что собственно и делается (вернее, эмулируется) в примере ниже.

Здесь можно посмотреть мини-демонстрацию использования моего логгера на примере плагина Tiny Scrollbar (как-то раз мне понадобилось модифицировать этот плагин под собственные нужды, и тогда этот логгер мне очень пригодился).

Замена console.log для кроссбраузерной отладки

Заключение

Описанный в данной статье способ призван помочь в устранении ошибок в веб-приложениях, связанных с особенностями различных браузеров и их платформ. Он может быть полезен при отладке различных событий, выявления нефатальных ошибок JavaScript, а также ошибок отображения (верстки).
Следует отметить, что существуют и другие, более «продвинутые» и изысканные решения, например от Yahoo: YUI 2 Logger, YUI 3 Console.

Спасибо за внимание.

Автор: xmeoff


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js