Как сделать обработчик событий

Обновлено: 07.07.2024

Цитатник веб-разработчиков В тексте курса вы встретите цитаты, высказанные в разное время разработчиками системы и разработчиками проектов на базе Bitrix Framework. Надеемся, что такие неформальные замечания внесут некоторое разнообразие в процесс изучения. Заодно опытные специалисты поделятся и своим опытом.

Имена авторов цитат даются в том написании, в каком авторы зарегистрировали себя на сайте "1С-Битрикс". .

Курс для разработчиков - продолжение линейки учебных курсов по Bitrix Framework. Получение сертификата по курсу рекомендуется после успешной сдачи тестов по всей линейке курсов, так как без понятия о работе Контент-менеджера и Администратора создание успешных сайтов будет затруднено.

Чтобы научиться программировать в Bitrix Framework, нет необходимости изучать всю линейку курсов. Но есть моменты, которые необходимо знать разработчикам о системе, они раскрыты в начальных курсах:

  • Интерфейс программы - в главе Элементы управления курса Контент-менеджер.
  • Компоненты 2.0 (начальные сведения) в главе Компоненты 2.0 (начальные сведения) курса Контент-менеджер.
  • Информационные блоки - в главе Информационные блоки (начальные сведения) курса Контент-менеджер.
  • Управление доступом к файлам, элементам контента, модулям и другие права доступа в главе Управление доступом курса Администратор. Базовый.
  • Работа с инструментами системы - в главе Работа с инструментами курса Администратор. Базовый.
  • Модуль Поиск - в главе Поиск курса Администратор. Базовый.
  • Вся информация по администрированию модулей размещена в курсах:
      - модули "1С-Битрикс: Управление сайтом" - модули "1С-Битрикс: Управление сайтом", связанные с коммерческой деятельностью в Интернете. - модули "1С-Битрикс: Корпоративный портал"

    Как построен курс

    Общепринятая градация квалификации разработчиков в рамках курса обозначает что:

    • Junior сможет создавать простые сайты работая со штатными компонентами и модифицируя их шаблоны.
    • Middle разработчик может работать с API Bitrix Framework.
    • Senior умеет работать над производительностью и безопасностью сайтов, создавать свои модули и компоненты.

    Примечание: Такое построение удобно для пошагового изучения принципов работы Bitrix Framework. По этому же принципу построены и тесты. Но такая структура не очень удобна для использования содержания курса как постоянного источника информации. Что бы переключить курс в режим Справочника, воспользуйтесь переключателем в верхнем правом углу шапки курса.

    Начальные требования к подготовке

    Для успешного изучения курса и овладения мастерством разработки сайтов на Bitrix Framework необходимо владеть (хотя бы на начальном уровне):

    • основами PHP, баз данных;
    • основами HTML, CSS.

    У нас часто спрашивают, сколько нужно заплатить

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

    Ещё у нас есть Академия 1С-Битрикс, где можно обучиться на платной основе на курсах нашей компании либо наших партнёров.

    Баллы опыта

    В конце каждого урока есть кнопка Прочитано! . При клике на неё в Вашу итоговую таблицу опыта добавляется то количество баллов, которое указано в прочитанном После нажатия кнопки Прочитано! появится
    окно подтверждения:


    уроке.

    Периодически мы заново оцениваем сложность уроков, увеличивая/уменьшая число баллов, поэтому итоговое количество набранных Вами баллов может отличаться от максимально возможного. Не переживайте! Отличный результат - это если общее число набранных Вами баллов отличается от максимального на 1-2%.

    Тесты

    После изучения курса вам будет предложено пройти тесты на сертификацию. При успешной сдаче последовательности тестов на странице Моё обучение можно просмотреть результат обучения и загрузить сертификат в формате PDF.

    Комментарии к статьям

    Что дальше?

    Одновременно с изучением курса Разработчик Bitrix Framework вам придётся обращаться к информации о других технологиях Bitrix Framework. Эта информация размещена в следующих курсах:

    Для преподавания оффлайн

    Если данный курс берётся в качестве основы для оффлайного преподавания, то рекомендуемая продолжительность: 5 дней (40 академических часов).

    Если нет интернета

    iPhone:
    FBReader
    CoolReader
    iBook
    Bookmate

    Windows:
    Calibre
    FBReader
    Icecream Ebook Reader
    Плагины для браузеров:
    EpuBReader – для Firefox
    Readium – для Google Chrome

    iOS
    Marvin for iOS
    ShortBook
    обновляются периодически, поэтому возможно некоторое отставание их от онлайновой версии курса.

    Если вы нашли неточность в тексте, непонятное объяснение, пожалуйста, сообщите нам об этом в комментариях.

    Обработчик события кнопки на JavaScript

    На предыдущих уроках по JavaScript, мы научились получать и изменять элементы на страницах. Но зачем это нужно, если можно сразу создать страницу с необходимым HTML кодом? Так мы и делаем всегда - сначала создаем статическую страницу, только одного этого недостаточно. Дело в том, что взаимодействие с пользователем происходит при помощи событий мыши или клавиатуры и нам надо как-то реагировать на эти события.

    Статичная кнопка

    У меня на сайте есть кнопка, при нажатии на которую ничего не происходит. Как заставить кнопку реагировать на клик пользователя (например менять текст на ней)?

    Обработчик события кнопки на JavaScript.

    Превращение статичной кнопки в интерактивную

    Вот теперь нам пригодится навык поиска элементов на странице.

    1) Шаг. Получение элемента, событие которого вы хотите обрабатывать.

    Мы хотим обрабатывать событие клика на элементе с идентификатором myBtn. Поэтому объявим переменную buttonElem и при помощи метода getElementById сохраним кнопку в эту переменную.

    const buttonElem = document.getElementById('myBtn');

    Создадим функцию с логичным названием onButtonClick. Функция должна заменить текст на кнопке, поэтому пропишем в теле функции выражение, которое изменит содержимое тега button. Обратимся к переменной и через свойство textContent заменим надпись на кнопке. Пока на данном этапе, при нажатии на кнопку ничего не происходит. Ведь браузер еще не знает, какую функцию ему вызывать при после клика на кнопку.

    let onButtonClick = function() buttonElem.textContent = 'Спасибо за клик'
    >

    3) Шаг. Связать обработчик события с событием клика и элементом.

    Ура! Наш JS код сработал, когда мы нажимаем на кнопку - меняется текст кнопки.

    const buttonElem = document.getElementById('myBtn');

    let onButtonClick = function() buttonElem.textContent = 'Спасибо за клик'
    >

    Обработчик события кнопки на JavaScript.

    Как работают функции?

    В примере используется функция обратного вызова (callback). Отличается она от обычной функции тем, что вызывается сразу после определенного события. В нашем случае, после события клика. Обычная функция выполняется сразу после загрузки страницы или через указанный интервал времени.

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

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

    В качестве второго аргумента можно передавать анонимную функцию. Анонимная функция не имеет имени и вместо имени вставляется инструкция (код JavaScript), что делает эта функция.

    buttonElem.addEventListener('click', function() buttonElem.textContent = 'Спасибо за клик'
    >);

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


    Если Вы не хотите пропустить новые материалы на сайте,
    то Вы можете подписаться на обновления: Подписаться на обновления

    Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

    Порекомендуйте эту статью друзьям:

    Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

    Она выглядит вот так:

    Комментарии ( 0 ):

    Итак, вспомним наш класс Person, который мы использовали, когда разбирали тему использования делегатов. Итоговый класс у нас выглядел следующим образом:

    • event — ключевое слово, которое сообщает нам, что перед нами событие
    • delegateType — это тип делегата. Делегат описывает то, как должен выглядеть метод в подписчике, который будет обрабатывать событие, а также то, какие параметры необходимо передавать подписчику. То есть, делегат, образно выражаясь, представляет из себя некий договор между издателем и подписчиком как они будут между собой общаться.
    • EventName — название события
    • sender — определяет класс или объект который породил событие (издатель)
    • e — класс, содержащий параметры, передаваемые подписчику.

    и затем объявить вот такое событие:

    Перепишем наш класс Person следующим образом:

    Обратим внимание на следующие моменты:

    1. Мы объявили событие типа EventHandler с названием ChangeDepartment — оно будет порождаться, когда у объекта будет изменяться название отдела
    2. Свойства Department вместо сокращенной формы записи теперь имеет блоки get и set . При этом, в блоке set проверяется действительно ли новое название отдела не совпадает с текущим и только, если новое название не совпадает со старым меняется значение у department и вызывается метод делегата.

    Теперь мы можем подписаться на это событие и получать уведомления от издателя. Сделать это можно, например, так:

    Здесь мы создали объект класс Person , и назначили в качестве обработчика события ChangeDepartment метод EventHandler . Теперь, если запустить приложение, то можно увидеть, что событие сработает ровно один раз:

    Как и в случае работы с обычными делегатами, методы EventHandler и EventHandler_2 будут вызваны последовательно:

    Но что, если нам потребуется, чтобы событие ChangeDepartment сообщало нам не только факт смены отдела, но и то, какой отдел был ранее? Здесь нам поможет создание собственного делегата события. Делается это следующим образом:

    Во-первых, создаем класс-наследник EventArgs который будет содержать необходимые параметры. Например, можем определить такой класс:

    здесь стоит обратить внимание на конструктор — в нем мы как раз передаем старое и новое название и присваиваем эти значения свойствам класса OldDepartment и NewDepartment .

    Во-вторых, объявляем делегат для события:

    В третьих, определяем событие в классе:

    В-четвертых, обеспечить внутри класса вызов события:

    Итого

    События применяются довольно широко. Примером могут служить всевозможные библиотеки, реализующие графический интерфес пользователя. Но события при правильном применении могут оказаться ДЕЙСТВИТЕЛЬНО ПОЛЕЗНОЙ ВЕЩЬЮ К сожалению исторически сложилось так, что в C++ нет событий. Поэтому при необходимости разработчики реализуют их на уровне библиотеки. Здесь вашему вниманию представлена реализация одной такой библиотеки. В ней есть два класса: Delegate и Event.

    Класс Delegate (делегат)

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

    В архиве, который прилагается к статье имеется заголовочный файл Delegate.h , в котором находится объявление и реализация класса Delegate. Для того, чтобы понять как используется этот класс рассмотрим пару примеров.

    Примеры использования класса Delegate

    Затем делаем объявление простого класса Test. Этот класс содержит в сбе частную переменную делегат. В неё мы будем подставлять функции нашего класса. Первым делом в конструкторе Test передаём делегату указатель на функцию Test::SayHello(). Как видно из реализации функции main, сразу после конструирования экземпляра Test происходит вызов функции Test::RunTest(). В ней то и заключена основная суть программы. После начала выполнения функции RunTest() делается вызов делегата как обычной функции C++

    Делегат передаёт этот вызов той функции, на которую он указывает. Если же делегат содержит NULL, то вызов игноррируется. Далее мы меняем функцию, на которую указывает делегат:

    Для демонстрации полученного эффекта повторно делаем вызов. При этом происходит вызов функции Test::SayGoodBye().

    Данный пример довольно прост, но всё же он демонстрирует возможности, которыми обладают делегаты и их основные преимущества.

    Пример №2: Небольшая база данных

    Теперь после первого знакомства с делегатами пришло время рассмотреть более сложный приём и понять, как можно применить делегаты в своих проектах. Предположим, что Вы проектируете небольшую базу данных для какого-нибудь предприятия. Эта база данных должна содержать в себе сведения о работниках предприятия. Эти сведения включают в себя:

    • Имя работника
    • Его оклад
    • Размер начисляемой премии (в %)
    • Категорию

    Размер заработной платы определяется с учётом премии. Добавим в программу класс служащего (Employe)

    • Объявление класса Employe находится в файле Employe.h
    • Реализация класса Employe находится в файле Employe.cpp

    Как видно из объявления класса он содержит в себе четыре частные переменные, которые содержат имя работника, его оклад, размер премии и категорию. Так как эти переменные частные, то доступ к ним осуществляется при помощи специальных функций. Также предоставляется специальный метод CalculateWage(), который возвращает зарплату работника в зависимости от премии

    Следующий класс, который мы добавим в наш проект будет представлять собой базу данных предприятия по рабочим. Назовём этот класс EnterpriseDB. Этот класс будет обладать минимальной функциональностью, но всё же он будет являться центральной частью нашего проекта.

    • Объявление класса EnterpriseDB находится в файле EnterpriseDB.h
    • Реализация класса EnterpriseDB находится в файле EnterpriseDB.cpp

    Класс EnterpriseDB в сущности представляет собой коллекцию указателей на объекты Employe. Имеется один метод для вставки объектов (EnterpriseDB::Add(std::string, int)). Метод принимает в качестве параметров имя работника и его категорию. Затем происходит выделение памяти под объект Employe* и вставка его в конец коллекции. В деструкторе EnterpriseDB уничтожает все указатели Employe*. С помощью метода SetupPayments(Employe *) происходит распределение окладов и премий в зависимости от категории служащего.

    Но самой важной функцией в классе, а возможно и во всей программе является функция ProcessStaff(Delegate &). С помощью этого метода можно для каждого из работников, находящихся в коллекции _staff произвести вызов метода, который скрывается за делегатом. Далее в основной функции программы main производятся несколько таких вызовов.

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

    • Объявление класса Accountant находится в файле Accountant.h
    • Реализация класса Accountant находится в файле Accountant.cpp

    Класс бухгалтера предоставляет следующие возможности. Он позволяет вести учёт рабочего с помощью метода AddEmployeToAccount(Employe *). При выполнении этого метода счётчик работников _count увеличивается на 1, а к общей зарплате _totalWage добавляется зарплата данного работника, которая вычисляется с помощью метода Employe::CalculateWage(). Метод GetTotalWage() возвращает количество денег, которые выплачиваются всем рабочим в качестве зарплаты. GetAverageWage() вычисляет среднюю зарплату по предприятию.

    Наконец пришло время написать главную функцию программы. Её реализация представлена ниже

    Результат выполнения программы приведён на рисунке ниже


    Разберёмся, что же происходит в этой программе. Во-первых, следует отметить новый класс, который выполняет в основном вспомогательные функции. Этот класс называется EmployeTester. Он имеет два метода. Первый из них - PrintInfo(Employe *) распечатывает информацию о сотруднике, который передаётся ему в качестве параметра. Второй метод AddEmployes(EnterpriseDB *) просто заполняет базу данных несколькими сотрудниками.

    Ну а сейчас перейдём к рассмотрению главной функции программы. Именно в ней происходят самые главные события, связанные с использованием делегатов. Сначала программа создаёт базу данных, бухгалтера и объект EmployeTester:

    Затем в базу данных вносятся сведения о трёх работниках:

    А теперь начинается самое важное. С помощью метода EnterpriseDB::ProcessStaff происходит назначение всем работникам зарплат и премий. Для этого методу ProcessStaff передаётся в качестве параметра делегат, который указывает на функцию EnterpriseDB::SetupPayments. Соответственно происходит вызов этой функции для каждого из работников в базе данных. Так служащему правильно назначается зарплата и премия в соответствии с его категорией:

    После установки начислений служащим в дело вступает объект EmployeTester. Он выводит на экран информацию о каждом из рабочих:

    А сейчас пришло время бухгалтеру подсчитать всех рабочих и определить суммарную зарплату и среднюю зарплату по предприятию. Результаты выводятся на экран:

    • Нужно вызывать только один метод
    • Вызывающему коду не нужно знать об объекте, которому принадлежит метод
    • Класс может иметь несколько реализаций одного метода

    Класс Event (событие)

    Событие в данном случае - это способ для класса оповестить клиентов (классов, использующих данный класс) о том, что с ним произошло что-то интересное. Наверное самый знакомый способ использования событий - в графическом пользовательском интерфейсе (GUI). Обычно классы, представляющие элементы управления (controls) в графическом интерфейсе имеют события, которые срабатывают, когда пользователь что-либо делает с элементом управления (например, нажимает на кнопку). Но события могут быть использованы не только в графическом интерфейсе. События обеспечиают действительно полезный путь для объектов сигнализировать об изменении своего состояния. Причём это изменение может быть важно для клиентов данного объекта. События - это важные строительные блоки для создания классов, которые могут быть повторно использованы во многих программах. События используются непосредственно вместе с делегатами. Важно помнить, что объекты - делегаты инкапсултруют (скрывают) метод класса и он может быть вызван анонимно. Событие - это способ вызвать методы других объектов, когда событие срабатывает. То есть сторонний объект помещает указатель на свой метод в делегат (как было показано ранее) и передаёт этот делегат событию. При срабатывании события вызывается делегат, а следовательно и тот метод, который был ему передан.

    Пример использования класса Event

    • Красная, зелёная и синяя составляющие цвета (RGB)
    • Строка display, предназнвченная для вывода цвета на экран

    Для удобства обращения с классом объявлены несколько статических констант - White, Black, Red, Green, Blue. Использовать класс Color можно следующим образом:

    Функция ToString() преобразует значение цвета в строку.

    Следующий класс называется View. Он содержит в себе одну переменную определяющую цвет. Класс предоставляет методы для получения/установки значения цвета - это соответственно GetColor/SetColor. Также в классе View есть событие ColorChanged , которое срабатывает, когда программа изменяет значение цвета, то есть вызывает метод SetColor.

    NewView - является производным классом от View. Его работа заключается в том, чтобы добавить свою функцию в событие ColorChanged, которое принадлежит его предку. Делается это в конструкторе NewView:

    Как видно, для того, чтобы передать свою функцию событию нужно сначала создать для неё обёртку ввиде делегата, а затем "прибавить" делегат к событию оператором +=.

    "Наблюдатель" за событиями (EventListener) фактически поступает также как и класс NewView. Он получает указатель на View и добавляет к событию ColorChanged свой метод EventListener::React():

    Отсоединение метода происходит также как и присоединение, только используется оператор -=.

    Рассмотрим главную функцию программы. Сначала программа создаёт объекты EventListener и NewView и выводит начальное значение цвета в объекте NewView:

    Читайте также: