• Home
  • Учебник по ExtJS
  • О сайте
  •  



    Кнопки: Библиотека ExtJS для новичков

    Эта статья является продолжением учебника по библиотеке компонентов ExtJS, используемой для создания web-приложений с функциональным интерфейсом пользователя.

    Один из самых простых компонентов библиотеки – кнопка (Button), создается тривиально:

    button = new Ext.Button({
     text: 'Кнопка',
     renderTo: Ext.getBody()
    })

    Что обычно требуется от кнопки? Правильно: реагировать на нажатия. Давайте определим специальную функцию ShowMessage(), которая будет выдавать простое сообщение пользователю о нажатии на кнопку:

    function ShowMessage() {
      Ext.MessageBox.alert("На меня нажали!", "Сообщение");
    }

    Присвоим ранее созданной кнопке эту функцию-обработчик.

    button.setHandler(ShowMessage)

    Обратите внимание, что многие начинающие разработчики в этом месте создают ошибку: указывают имя функции со скобками ShowMessage() вместо ссылки на нее как на объект ShowMessage, что приводит к вызову функции, а потом передаче в качестве параметра возвращенного ей результата, что неверно.

    Щелкаем по кнопке – получаем сообщение:

    Функцию-обработчик можно задавать напрямую в конфигурации компонента как анонимную функцию:

    button = new Ext.Button({
      text: 'Кнопка',
      renderTo: Ext.getBody(),
      handler: function() { Ext.MessageBox.alert("На меня нажали!", "Сообщение"); }
    })

    Для удобства нескольким кнопкам можно присваивать один обработчик. Обратимся к новому примеру:

    function ButtonClick() {
      Ext.MessageBox.alert("На меня нажали!", "Сообщение");
    }
    
    for (i=1;i<=10;i++) {
      new Ext.Button({
        text: 'Кнопка номер '+i,
        renderTo: Ext.getBody(),
        handler: ButtonClick,
        id: 'button_'+i
     })
    }

    Теперь при нажатии на любую из созданных в цикле десяти кнопок будет запускаться одна и та же функция:

    Обратите внимание, что на этот раз мы не сохраняем созданный в результате вызова конструктора кнопки объект, а задаем в его конфигурации параметр id вида button_N, где N – порядковый номер кнопки. В дальнейшем зная идентификатор компонента можно получить его объект конструкцией:

    Ext.getCmp(‘button_N’)

    Следующий цикл выполняет перебор ранее созданных кнопок и их переименование:

    for (i=1;i<=10;i++) {
      Ext.getCmp('button_'+i).setText('Кнопочка '+i)
    }

    Интересно, а можно с помощью всего лишь одной функции-обработчика сделать привязку к нажатой кнопке? Переопределим функцию-обработчик, добавив ей два параметра: button (объект кнопки, которая была нажата) и e (тип полученного обработчиком события):

    function ButtonClick(button, e) {
      Ext.MessageBox.prompt("Изменить?", "Введите новое название кнопки", function(btn, text) {
      if (btn == 'ok') {
       button.setText(text)
      }
     })
    }

    К сожалению, простого переопределения функции в Firebug с таким же именем для привязки к ранее созданным кнопкам недостаточно. Снова переберем существующие кнопки и присвоим новый обработчик:

    for (i=1; i<=10; i++) {
     Ext.getCmp('button_'+i).setHandler(ButtonClick)
    }

    Проверяем: кнопки переименовываются!

    В обычном HTML кнопка задается подобными тегами:

    <input type="submit" id="btnLaunch" value="Lancer" name="btnLaunch"/>

    А что представляет из себя компонент-кнопка из библиотеки ExtJS в DOM-документе? Вы будете смеяться, но это таблица с декоративными элементами и тегом <button>:

    <table cellspacing="0" cellpadding="0" border="0" class="x-btn-wrap x-btn x-btn-text-icon"
     id="ext-comp-1169" style="width: auto;">
      <tbody><tr>
       <td class="x-btn-left"><i> </i></td>
       <td class="x-btn-center"><em unselectable="on">
       <button type="button" class="x-btn-text" id="ext-gen138" style="background-image: url(/img/settings.gif);">
       Profile</button></em></td><td class="x-btn-right"><i> </i>
       </td></tr>
      </tbody>
    </table>

    Внутренняя структура одной из наших кнопок в Firebug:

    Давайте посмотрим, как можно управлять положением кнопок с помощью изменения свойств их DOM-элементов.

    function getBrowserHeight() {
      return document.compatMode=='CSS1Compat' && !window.opera?
        document.documentElement.clientHeight:document.body.clientHeight;
    }
    
    function getBrowserWidth() {
      return document.compatMode=='CSS1Compat' && !window.opera?
       document.documentElement.clientWidth:document.body.clientWidth;
    }
    
    for (i=1;i<=10;i++) {
      dom = Ext.getCmp('button_'+i).el.dom;
      dom.style.position="absolute";
      dom.style.marginLeft=Math.round(Math.random()*(getBrowserWidth()-dom.clientWidth));
      dom.style.marginTop=Math.round(Math.random()*(getBrowserHeight()-dom.clientHeight));
    }

    Выше мы определили две кроссбраузерные функции getBrowserHeight() и getBrowserWidth(), которые будут оценивать доступную область экрана (соответственно высоту и ширину) браузера в пикселах. Далее в процессе цикла перебираем все кнопки и присваиваем им абсолютные координаты, сгенерировав их из случайных значений. Обратите внимание, что мы подсчитываем метрику окна браузера, вычитаем из этого значения метрику кнопки (чтобы не появлялись полосы прокрутки) и на основании полученной величины присваиваем верхней или левой координате DOM-элемента кнопки случайное значение из этого диапазона:

    Теперь немного позабавимся: сделаем так, что кнопки заживут своей жизнью. Давайте представим, что каждая кнопка будет двигаться в собственном направлении, которое определяется двумя переменными кнопки moveX и moveY, имеющими значения -1 (для сдвига против оси), 0 (без изменения по оси) и 1 (для сдвига по оси). Для удобства зададим функцию-генератор этих значений:

    function getDirection() {
     return Math.round(Math.random()*2)-1;
    }

    Задаем первоначальные направления движения кнопкам:

    for (i=1;i<=10;i++) {
      Ext.getCmp('button_'+i).moveX = getDirection();
      Ext.getCmp('button_'+i).moveY = getDirection();
    }

    А теперь реализуем функцию crazy(), которая будет осуществлять движение:

    function crazy() {
      for (i=1;i<=10;i++) {
        comp = Ext.getCmp('button_'+i)
        X = parseInt(comp.el.dom.style.marginLeft);
        X += comp.moveX;
        if ((X == 0) || (X == (getBrowserWidth()-comp.el.dom.clientWidth))) {
          comp.moveX = invertDirection(comp.moveX);
        }
        comp.el.dom.style.marginLeft = X;
        Y = parseInt(comp.el.dom.style.marginTop);
        Y += comp.moveY;
        if ((Y == 0) || (Y == (getBrowserHeight()-comp.el.dom.clientHeight))) {
          comp.moveY = invertDirection(comp.moveY);
        }
        comp.el.dom.style.marginTop = Y;
      }
    }
    
    function invertDirection(dir) {
      if (dir == -1) { return 1; }
      if (dir == 1) { return -1; }
      return 0;
    }

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

    Запускаем в работу:

    setInterval(«crazy()», 100)

    Заметьте, что во время отображения всплывающего окна с сообщением при нажатии любой кнопки, их движение продолжается несмотря на то, что выводится модальный диалог.

    Что еще можно делать с кнопками?

    1. С помощью метода focus() определенной кнопке можно передать фокус ввода.
    2. К кнопке можно привязать выпадающее меню (свойство menu конфигурации компонента и его методы showMenu и hideMenu)
    3. Кнопка может работать в режиме переключателя (свойства enableToggle, pressed, toggleHandler и toggleGroup в конфигурации и свойство объекта toggle)
    4. Кнопку можно заблокировать (свойство disabled в конфигурации)
    5. К кнопке можно добавить изображение-иконку (свойство icon в конфигурации и его метод setIconClass)
    6. К кнопке можно добавить всплывающую подсказку (свойства tooltip и tooltipType в конфигурации)

    Перейти далее к разделу Расширенная работа с панелями…

    Перейти к содержанию Учебника по ExtJS

    5 Responses to “Кнопки: Библиотека ExtJS для новичков”

    1. | setInterval(«crazy()», 100)
      crazy же в данном случае надо писать без скобок…

    2. missterr:

      Абсолютно не понятно для чего нужен параметр «е» в функции
      function ButtonClick(button, e) {
      Ext.MessageBox.prompt(«Изменить?», «Введите новое название кнопки», function(btn, text) {
      if (btn == ‘ok’) {
      button.setText(text)
      }
      })
      }
      Так же не плохо было бы объяснить в тексте что в callback функцию автоматом передается код нажатой пользователем кнопки и введенный им текст.

    3. missterr:

      Автор, вы мне так и не скажете для чего нужен параметр «e» в функции:

      function ButtonClick(button, e) {
      Ext.MessageBox.prompt(«Изменить?», «Введите новое название кнопки», function(btn, text) {
      if (btn == ‘ok’) {
      button.setText(text)
      }
      })
      }
      Код работает и без него.

    4. smarteen:

      Хорошие статьи, как раз для самых начинающих.
      Пишите еще!

    5. padovan:

      А примерчик доходчивый можно по кнопке toggle. Ато чото пишет enableToggle – не функция

    Leave a Reply