Lumber room
28 January 2010

Добавляем окнам ExtJS плашку ошибки

Сообщение об ошибке в окнеЗдравствуй, Хабрачеловек! Сейчас я тебе поведаю о маленьком расширении Ext.Window из популярного в каких-то кругах JavaScript Framework-а ExtJS. Это расширение призвано блокировать отдельное окно и отображать сообщение об ошибке.

Я рассчитываю что ты знаешь что такое ExtJS, но не на много лучше меня, а то тебе будет неинтересно…



Есть в ExtJS компонент — Ext.Window, который является окошком. И есть у него тело (свойство) — body, у которого есть метод mask(), потому что он Ext.Element. Этот метод накрывает окошко пеленой, намекая пользователю что надо чего-то подождать. Можно так же вывести некий текст, объясняющий чего собственно приходится ждать. Для этого нужно передать в метод строку сообщения.

Так вот, нужен был мне такой метод, который сообщал бы об ошибке именно для этого окна, не действуя на другие части интерфейса. Но при этом требовал отклика пользователя, т.е. чтоб у пользователя небыло подозрения «что-то не работает», а он знал «ага, вот это не работает и вот почему!». Этот метод должен легко вызываться и шустро отрабатывать, а заодно быть частью класса окна. Т.к. одновременно работающих окон может быть много, то стандартные средства сообщения об ошибке(Ext.MessageBox), ввиду их модальной работы, мне не подходили даже близко.

Покопавшись в недрах mask() и обратного ему unmask() было решено расширить класс окна своим методом на основе этих двух. Посмотрев как работает mask(str) я понял что он не очень мне подходит, т.к. не предоставляет готовых контейнеров. Но благодаря трепанации этого метода я разобрался в CSS плашки.
Окно, накрытое маской
Не долго думая накидал панельку, в которой уютно разместил строку сообщения, иконку ошибки и кнопку «Ok»:
new Ext.Panel({
          renderTo: SomeDom,
          width: 200,
          height: 80,
          border: false,
          cls: 'win-error-mask',
          bodyCfg: {cls: 'win-error-mask-icon'},
          html:'Тут сообщение об ошибке. Оно может быть длинным...',
          buttonAlign: 'center',
          buttons: [new Ext.Button({
              text: 'Ok',
              width: 70,
              handler: function (){  
              }
            })]
          }
          );


Поэкспериментировав с панелью добился нужного мне отображения, после чего начал писать для неё CSS на основе того, что увидел в mask. Фактически все было уже готово, надо было лишь натянуть это на панель да изменить цвета. Вышло 4 вот таких доработанных клона:
.win-error-mask {
  z-index: 20001;
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid;
  background: repeat-x 0 -16px;
  padding: 2px;
  border-color: #e03939;
  background-color: #fe9295;
  background-image: url(resources/tb-red.gif);
}

.win-error-mask div.x-panel-bwrap {
  padding: 5px 10px 0px 10px;
  border: 1px solid;
  border-color: #f86c6c;
  background-color: #fff;
}

.win-error-mask div {
  background-color: #fff;
  color: #222;
  font: normal 11px tahoma, arial, helvetica, sans-serif;
}

.win-error-mask-icon {
  background: transparent no-repeat center left;
  background-image: url(resources/icon-error.gif);
  padding-left: 40px;
  padding-bottom: 36px;
}

Замечу что привинчивать эти CSS я начал на простой панели, пока она ещё не была частью расширения класса Ext.Window, т.к. в ExtJS особенно актуальна восходящая модель разработки при реализации блоков логики.

Далее дело было за малым — обернуть все это в функцию и прилепить к классу окна. На сайте ExtJS куча документации по работе с классами и ООП в ExtJS, так что если что-то непонятно, RTFM. А вот мой результат с парой комментариев:
Ext.ux.Window = Ext.extend(Ext.Window, {
  errorMaskPanel: null, // панель тут для удобства обращения
  errorMask: function(errorMsg){
    this.body.mask(); // Накрываем окно маской
    this.errorMaskPanel = new Ext.Panel({ // Создаем панель...
      renderTo: this.body.dom, // По аналогии с mask(str) рисуем в тело окна
      width: 200,
      height: 80,
      border: false,
      cls: 'win-error-mask',
      bodyCfg: {
        cls: 'win-error-mask-icon'
      },
      html: errorMsg,
      buttonAlign: 'center',
      buttons: [new Ext.Button({
        text: 'Ok',
        width: 70,
        handler: function(){ // Ну и по нажатию Ok все убираем
          this.body.unmask();
          this.errorMaskPanel.destroy();
        },
        scope: this // Функция работает в контексте окна
      })]
    });
    
    this.errorMaskPanel.el.center(this.body.dom); // Центрируем...
  }
});


*да, я упаковал все в свой класс Window в пространстве ux, а не заместил стандартный Ext.Window

Вот так легко и просто (может где-то ещё и криво) расширяются базовые классы ExtJS.

+10
451 8
Comments 5
Top of the day