Добавляем окнам 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.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 5

      0
      Окно с одной кнопкой доставляет пользователю неудобство, ему нужно отвлечься и выполнить действие, которое не повлечет за собой результата. В таком примере время пользователя тратится напрасно. Модальные окна нужно использовать, если операция требует немедленного вмешательства и состоит из более чем 2х вариантов решения.

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

      Конечно, это не касается extjs, но имейте в виду при разработке.
        0
        С вами нельзя не согласиться, и даже вы в абсолюте правы если приложение модальное.

        Но я пришел к такому методу, т.к. при модальном окне ошибки в многооконном (но не модальном) приложении возникают проблемы с отнесением ошибки к конкретному окну. Если у меня три окна, в одном из них ошибка — модальное сообщение блокирует все окна, а мое сообщение только то, в котором ошибка. Пользователь узнает о ней когда обратит свое внимание на это окно, а не когда это окно заставит его посмотреть что случилось.

        Т.е. я как-раз думал о том что не стоит прерывать работу пользователя модальным окном, если ошибка не затрагивает работу всей системы.
          0
          а что будет если вслед за первым модальным окном придет запрос на открытие второго?
            0
            В ExtJS MessageBox — Singleton. Второе окно появится вместо первого. Можно покопаться и сказать точно как это работает, но внешне произойдет именно так. Т.е. предыдущее окно будет утеряно. Этого можно избежать используя простые окна в модальном режиме. Тогда новое окно перекроет старое, и после закрытия нового окна — старое будет снова видно.
          0
          спасибо. просто и гениально.
          я немного упростил и получил то, что давно хотел.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое