Где хранятся параметры канбана битрикс 24
Модель подходит для веб-студий, работающих с большим количеством несложных заказов. Работа по этой модели — это работа без конечных сроков. Клиент платит за то, что студия потратила время. При доверии со стороны клиента, что программист работает эффективно и поставленную задачу реально можно было решить именно за то время, которое на неё потрачено.
Канбан позволяет сократить время прохода задачи до состояния «готовности». Количество незавершённой работы разработчика должно быть ограничено. Новая задача может ставиться только тогда, когда какая-то из существующих передаётся следующему элементу производственного цикла. Kanban (или сигнальная карточка) подразумевает, что производится некое визуальное оповещение о том, что можно задавать новую работу, так как текущий объём работ не равен принятым лимитам.
Смысл системы с точки зрения разработчика: максимально упростить бюрократию и дать человеку просто работать над небольшим числом задач.
Смысл системы с точки зрения веб-студии: снижение времени прохождения задачи через группу специалистов до её релиза. Система позволяет создать работнику такие комфортные условия работы, что бы задача проходила через все эти этапы быстро. При этом происходит визуализация задач, облегчающая контроль.
Нет планирования времени. На доске размещаются столбцы специалистов. В столбцах специалистов указывается лимит на число задач, которые «висят» на специалисте. Больше этого числа задач им нельзя ставить. Не должно быть такого, что прибегает кто-то и: «Срочно нужно сделать!», все делается только в порядке установленном на доске.
Менеджер может визуально отслеживать состояние дел: где происходит «затык» в работе, кто отстаёт и начать разбираться почему это происходит и принимать меры по устранению проблем.
На одной доске можно вести учёт всех проектов, если, например, определить для каждого проекта свой цвет задач. На карточках можно указывать время начала работы и время её завершения.
Канбан доска
Для владельцев коммерческих тарифов уже доступны от 2 до 10 приложений в рамках интеграционного пакета. Подробно изучить возможности полного каталога готовых решений Битрикс24 Маркет Плюс вы можете в бесплатном 15-дневном демо-режиме.
Канбан доска
По подписке
Установить
Информация
Опубликовано : 15.07.2019
Установок : 580
Другие приложения разработчика

KPI – Эффективность работы компании
По подписке

Служба поддержки
По подписке

Управление проектами
По подписке







«Канбан доска» — это дополнительная возможность оптимизации всех процессов, переход от записок и блокнотов к системе электронной фиксации данных, которые будут доступны каждому сотруднику.
Основной функционал.
Приложение «Канбан доска» – это многофункциональный помощник, который обладает рядом возможностей.
Настройка приватных и публичных досок с заметками. Заметки могут создаваться не только для себя, но также для группы сотрудников, если работа в компании ведется совместно. Для удобства в системе настроек можно выбрать приватный режим, при котором просматривать и менять данные могут лишь выбранные для этого участники, либо публичный режим, где просматривать могут все сотрудники компании, а менять данные лишь избранные.
Гибкая настройка прав участников. Интерфейс приложения максимально прост – здесь легко можно добавлять участников нажатием всего одной кнопки, и также быстро удалять их из заметки. При добавлении участника можно выбрать один из возможных вариантов доступа: администратор, редактор, просмотр.
Добавление досок с заметками в избранное, привязка досок к группам или проектам Битрикс24. Во время настройки в приложении можно выбирать рабочий проект из выпадающего списка доступных. Это позволяет хранить всю необходимую информацию по делу, не обращаясь к справочникам, телефонным книгам и иным источникам информации.
Добавление неограниченного количества колонок, возможность их копирования или ротации. В интерфейсе доски каждая колонка отображается в виде отдельного окна. Чтобы создать новую с аналогичными данными, необязательно проходить процедуру разработки с нуля. Достаточно скопировать имеющуюся заметку и лишь подкорректировать данные. Также можно свободно размещать заметки по рабочему столу в порядке важности или просто как удобно.
Добавление неограниченного количества колонок, возможность их ротации как внутри, так и между колонками. Все колонки с делами существуют отдельно. К примеру, на рабочем столе есть три колонки – срочные дела, в процессе и завершено. Каждая колонка содержит ряд карточек с описанием дел или иными заметками. Например, при просмотре срочных дел сотрудник может взять одну карточку и легким движением мыши перетащить ее в соседний столбик в группу выполняемых задач. Также могут меняться местами задачи в одной колонке – это позволяет визуализировать приоритеты, понятнее формировать список дел на период и упрощает работу.
Добавление заметок для карточек. При формировании карточки дела, при ее просмотре с возможностью редактирования пользователю откроется окно с несколькими полями. В них можно задать название карточки (рабочего процесса, задачи, напоминания), а также дополнительно дать описание или примечания по вопросу. При просмотре в дальнейшем это позволит быстро вспомнить важную информацию и не тратить время на новые поиски данных.
Функционал поиска по карточкам в доске. В приложении имеется система поиска, благодаря которой нужные сведения могут быть сразу найдены по запросу (фразы) или дате создания (редактирования) карточки.
Функционал смены фона. Приложение также позволяет играть с оформлением и менять его под настроение или стилистику компании. При смене фона можно использовать изображения или сделать его однотонным цветом.
Функционал фиксации истории действий. В левой части приложения отображается информация о том, какие пользователи производили действия на досках. Информация предоставляется в виде списка действий в убывающей последовательности. В списке указывается имя и фамилия пользователя, действие, дата и время его совершения. Это позволит легко контролировать деятельность сотрудников и отслеживать изменения информации.
Версия 2
Добавлен функционал создания задач из заметок.
Версия 1
Канбан доска — это великолепный планировщик задач по проекту. Вы можете создавать списки дел и любую другую информацию, для которой раньше требовались стикеры.
- видимость: приватная/публичная;
- проект;
- фон: цвет/фотография;
- участники.
- создавать и редактировать колонки;
- создавать и редактировать карточки;
- осуществлять поиск по карточкам;
- видеть последние действия по доске.
Режим работы:
10:00 — 19:00 по московскому времени.
Время реакции на обращение – 48 часов.
Выходные дни: суббота и воскресенье.
Канбан в CRM
У большинства компаний, которые продают товары и услуги, есть выстроенный процесс работы с клиентами. Он состоит из регламентов и этапов работы. Не важно, какой размер или сфера деятельности компании. Во всех случаях есть общие точки контакта с клиентами: звонки, встречи, письма, смс, договоры или счета.
Один из инструментов, которые помогают выстраивать работу с клиентами — Канбан. Это способ отображения лидов и сделок, в котором вы увидите, сколько сделок и на какую сумму находятся на той или иной стадии работы, запланировали ли менеджеры встречи с клиентами, получите базовую аналитику эффективности работы сотрудников.

Логика отображения иконки пользователя в карточке элемента
В иконке находится изображение сотрудника если он:

- Создал карточку элемента.
- Автор дела, срок выполнения которого скоро наступит. Например, срок выполнения дела 15.00 за 15 минут до этого времени в иконке будет фото автора.
- Ответственный за входящее обращение. Входящее обращение — это чат.
Канбан будет особенно полезен компаниям, в которых менеджеры работают с большим количеством сделок. Когда их число превысит десятки или сотни, менеджер не запомнит информацию обо всех клиентах и обязательно кого-нибудь забудет. Благодаря канбану сотрудник всегда будет знать, с кем из клиентов нужно связаться, оформить доставку или выставить счёт.
Возможности канбана
В канбане можно создавать и настраивать стадии сделок.
Как настраивать стадии
Наведите мышку на стадию и нажмите на карандаш. В режиме редактирования вы можете изменить название и цвет, удалить стадию или переместить.

Чтобы создать стадию, наведите мышку на любую из стадий и нажмите на плюсик.

В канбане можно создавать, удалять сделки и перемещать на другие стадии.
Как перемещать сделки на другие стадии
Прямо в канбане сделку можно перенести на любую из стадий или даже удалить. Для этого перетащите сделку на соответствующее поле.

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

В открывшемся окне выберите нужные поля и сохраните изменения.

После этого в карточке появятся поля, которые вы выбрали.

В канбане можно фильтровать сделки по полям и условиям, например, отобразить сделки конкретного сотрудника.
Как настраивать фильтр
Нажмите на окно поиска, а затем на Добавить поле. Отметьте поля, которые вам нужны.

Выберите нужные значения полей и нажмите Найти.

В канбане останутся только те сделки, которые подходят под выбранные условия.

Вы можете отслеживать, есть ли запланированные дела с конкретной сделкой или про неё забыли. При необходимости можно запланировать дело прямо в канбане.
Как отслеживать и планировать дела
У каждой карточки в канбане есть кнопка Дела. Нажмите на неё, чтобы узнать, есть ли запланированные дела по этой сделке.

Если дел нет, то вы можете запланировать их. Для этого нажмите Запланировать, выберите тип дела и укажите детали, например, время и тему звонка.
Изменяем пользовательский интерфейс коробочного Битрикс24

Всем привет!
Продолжаем учиться правильно кастомизировать Битрикс24
Сегодня же рассмотрим варианты решения одной из самых частых задач в коробке — как изменить пользовательский интерфейс. Добавить кнопку или дополнительную информацию, изменить поведение штатных элементов управления.
Казалось бы, что тут сложного?
Скопировали шаблон компонента в свое пространство имен и кастомизировали как душе угодно. Но это, мягко говоря, не самый лучший подход. Использование папки local — так же «не идеально».
Почему же так и какие есть варианты решения задач — мы вам и расскажем.
В этой статье демонстрируются 4 подхода на нескольких практических примерах. Они позволят вам «не ходить по граблям» самому, перенять полезный опыт и решать задачи эффективно. С нами снова делятся опытом коллеги из Интерволги .
В изучении этой темы вам поможет исходный код примеров из статьи, а так же запись вебинара, на котором мы показали решения «в живую»:
Под катом подробная статья, слово коллегам из Интерволги:
[spoiler]
Отличие подходов к доработке Б24 и сайта на БУС
Считайте Битрикс24 сайтом, разработанным на БУС – платформа, технологии – те же. Битрикс24, как и любой другой сайт, включает шаблоны сайта, публичную часть (разделы и страницы), компоненты и шаблоны компонентов. Однако при установке обновлений публичная часть тоже обновляется. Поэтому публичную часть, шаблоны сайта и компонентов так же можно считать ядром Битрикс24.
Как известно, вносить изменения в ядро нельзя. В Битрикс24 это означает, что нельзя изменять не только файлы Bitrix Framework, но и публичную часть, шаблоны сайта и компонентов. Как минимум потому, что ваши изменения будут удалены при очередном обновлении.
С копированием шаблонов компонентов ситуация еще интереснее.
Во-первых, даже если вы скопировали шаблон в каталог local с тем же именем, что и оригинальный, система будет подключать его всегда, вне зависимости от обновлений. Это, как минимум, означает, что после очередного обновления клиент не увидит новых функций, а также не будут исправлены ошибки в этом шаблоне, если они есть. Но это не самое страшное.
Во-вторых, компоненты Б24 представляют собой целостную систему и их код написан исходя из предположения, что во всей системе используются оригинальные шаблоны. Это означает, что кастомизированные шаблоны не ожидаются системой. Кастомизированный шаблон может привести к информационной несовместимости с остальными частями системы и стать источником странных, трудноуловимых ошибок.

- Работает и в облаке и в коробке одинаково, легко перенести код.
- Не является «хаком», поддерживается архитектурой.
- Вызывается в iframe, вы ограничены работой в нем.
- Лишний объем работы для коробки: требуется создать «приложение».
- Просто в реализации.
- Работает со стороны сервера, появится сразу при загрузке страницы.
- Не так много точек для встройки и они могут измениться со временем.
- Работает и в облаке и в коробке.
- Не является «хаком», поддерживается архитектурой продукта.
- Точек для встройки мало, они фиксированы по расположению
- Необходимо создать поле для объекта с кастомным типом и контролировать что его не удалят
- Нет ограничений для точек и логики встройки.
- Это «хак» системы. Обновление шаблонов может потребовать доработки вашего кастома.
- Ваше решение подгружается после загрузки DOM в браузере, это может быть заметно для пользователя.
В REST-интерфейсе Б24 предусмотрена функция встраивания приложений в различные части интерфейса. Далее приводится лишь перечень этих мест (плейсментов). За дополнительной информацией обращайтесь к документации , пройдите курс “Маркетплейс Битрикс24” ( текcтовый , видео-уроки ), а также посмотрите вебинары Сергея Вострикова по этой теме [ прим. этот способ не требует доп пояснений, фактически это создание «приложения» для Битрикс24 на REST.API, что уже подробно рассмотрено в указанных материалах ].

Контекстное меню сущности CRM в списке

Вкладка в карточке сущности CRM

Действие в ленте сущности CRM

Карточка звонка
Типы пользовательских полей
Также REST-приложения могут регистрировать собственные типы пользовательских полей. Они могут быть использованы везде, где есть возможность добавить такие поля.
Пример поля REST-приложения в карточке CRM. Просмотр:


2. Отложенные функции
Разработчики сайтов на платформе БУС хорошо знакомы с отложенными функциями. Если вкратце, то в любом месте (шаблоне сайта, компонента и т. п.) можно вызвать $APPLICATION->ShowViewContent, затем, используя метода шаблона SetViewTarget/EndViewTarget или $APPLICATION->AddViewContent, добавить верстку в отложенную область. Причем не важно, в какой момент будет добавлена верстка, главное, чтобы это было сделано в рамках одного хита.
Если вы посмотрите на код шаблона сайта (/bitrix/templates/bitrix24), то увидите некоторое количество вызовов ShowViewContent. Штатные компоненты системы используют эти отложенные области для встраивания своих элементов. Но и вы тоже можете добавлять свою верстку!
Важно! Это «недокументированная возможность». Названия областей могут измениться со временем без предупреждения.
В качестве примера добавим свою кнопку в строку заголовка [ пример на вебинаре ]. Следующий код можно запустить из init.php.
use Bitrix\Main\UI\Extension; Extension::load('ui.buttons'); Extension::load('ui.buttons.icons'); // Пример 1: Добавляем кнопку. ob_start(); ?> Отчет AddViewContent('inside_pagetitle', $customHtml, 20000);
Кнопку мы создаем с помощью модуля UI-библотека (ui). Сначала подключаем расширения «стили кнопок» (ui.buttons) и «иконки для кнопок» (ui.buttons.icons) с помощью класса Extension главного модуля. После этого необходимые стили будут загружены браузером.
Саму кнопку «Отчет» формируем с помощью HTML. Она ничего не делает, цель — научиться встраивать элементы.
Кнопку добавляем с помощью $APPLICATION->AddViewContent. Обратите внимание на третий аргумент. Это значение сортировки. Задавать его необязательно, но с его помощью вы можете регулировать положение вашего элемента относительно других в этой области.
У нас получится следующее:

3. Типы пользовательских полей
Можно использовать возможность типов пользовательских полей встраивания в карточки сущностей. Не обязательно делать настоящее поле, можно вывести свою верстку.
Однако этот способ работает только для карточек и списков. При этом само поле нужно создать в системе и следить за тем, чтобы его не удалили.
Чтобы создать свой тип пользовательского поля в коробке, необходимо объявить класс этого поля и зарегистрировать его в системе с помощью события OnUserTypeBuildList [ пример на вебинаре ]
class MyUserType extends TypeBase < const USER_TYPE_ID = 'myusertype'; function GetUserTypeDescription () < return array( 'USER_TYPE_ID' =>static::USER_TYPE_ID, 'CLASS_NAME' => __CLASS__, 'DESCRIPTION' => 'Кастомное поле', 'BASE_TYPE' => \CUserTypeManager::BASE_TYPE_STRING, 'EDIT_CALLBACK' => array( __CLASS__, 'GetPublicEdit' ), 'VIEW_CALLBACK' => array( __CLASS__, 'GetPublicView' ) ); > function GetDBColumnType ($arUserField) < global $DB; switch (strtolower($DB->type)) < case "mysql": return "text"; case "oracle": return "varchar2(2000 char)"; case "mssql": return "varchar(2000)"; >> public static function GetPublicView ($arUserField, $arAdditionalParameters = array()) < Extension::load('ui.buttons'); return 'Button From Custom Field'; > public static function GetPublicEdit ($arUserField, $arAdditionalParameters = array()) < Extension::load('ui.buttons'); $name = static::getFieldName($arUserField, $arAdditionalParameters); return '' . 'Button From Custom Field'; > >
Наследовать класс своего поля от класса другого поля может быть удобно, однако вы рискуете получить неправильную форму наследования. Поэтому, рекомендуется наследовать свой класс от TypeBase — базового класса всех типов пользовательских полей.
Важно определить константу USER_TYPE_ID (именно с таким именем). Она используется системой для различения типов полей.
Метод GetUserTypeDescription должен возвращать описание поля для системы: ID типа поля, класс-обработчик поля, название в интерфейсе управления пользовательскими полями, методы визуализации поля. Этот метод должен являться обработчиком события OnUserTypeBuildList.
$eventManager = EventManager::getInstance(); $eventManager->addEventHandlerCompatible('main', 'OnUserTypeBuildList', array( 'MyUserType', 'GetUserTypeDescription' ) );
Метод GetDBColumnType используется при создании поля нашего типа в какой-либо сущности. Он возвращает физический тип данных для СУБД.
Нас интересуют методы GetPublicView и GetPublicEdit. С помощью них происходит визуализация поля в карточках сущностей в публичной части. Они оба должны возвращать HTML. Выведем кнопки разных цветов с помощью модуля ui.
Помните, что некоторые карточки сущностей не отображают поле в режиме просмотра, если оно не заполнено. Чтобы быть уверенным, что при сохранении данных поле оказалось заполненным, в методе GetPublicEdit также выводится скрытый input.
Вот, что у нас получилось:
| В режиме просмотра сделки | В режиме редактирования сделки |
![]() |
![]() |
4. Модификации на стороне клиента (JavaScript)
С помощью JavaScript можно произвольным образом менять внешний вид КП на стороне клиента, в том числе добавлять свои элементы элементы управления с нужным вам поведением.
- Однако этот способ обладает рядом ограничений, которые вы должны принимать во внимание:
- При включенном объединении JS в настройках главного модуля появление вашего скрипта на клиенте не полностью под вашим контролем. Требуется организовывать свой код определенным образом.
- При очередном обновлении верстка может измениться. Вам необходимо следить за тем, чтобы обновление не привело к ошибкам в вашем коде и своевременно его актуализировать.
- Код исполняется на стороне клиента. Но вы точно не знаете какой именно на этой стороне браузер. Ваш код должен быть кроссбраузерным.
- С различными фрагментами DOM-дерева может быть связана штатная клиентская логика, например, канбан сам обновляется. Это приводит к динамическому изменению DOM-дерева, ваш код должен корректно реагировать на эти изменения.
- В целях обеспечения эргономичности, некоторыми штатными функциями КП можно воспользоваться из нескольких мест (например, задачу можно завершить с детальной страницы, из списка и пр.). Встраиваемые вами элементы (в лучшем случае) должны подчиняться той же логике (то есть быть продублированы в разных интерфейсах). Это особенно актуально, если задача связана с ограничением доступа.
Общий подход
Где создать JS-файл и как его правильно подключить со всеми зависимостями?
- /local/js/custom_stuff.js
- /local/css/custom_stuff.css
- /local/lang/ru/custom_stuff.js.php
- /local/tools/custom_stuff/disk_templates.php
CJSCore::RegisterExt('custom_stuff', array( 'js' => '/local/js/custom_stuff.js', 'lang' => '/local/lang/' . LANGUAGE_ID . '/custom_stuff.js.php', 'css' => '/local/css/custom_stuff.css', 'rel' => array( 'ajax', 'popup' ) ) ); CJSCore::Init('custom_stuff');
Для проверки напишем в custom_stuff.js функцию helloWorld, чтобы проверить, что все корректно подключилось. Весь код поместим в пространство имен CustomStuff.
var CustomStuff = BX.namespace('CustomStuff'); CustomStuff.helloWorld = function() < alert(BX.message('CUSTOM_STUFF_HELLO_WORLD')); >;
А в файл языковых констант добавим строку:
$MESS['CUSTOM_STUFF_HELLO_WORLD'] = 'Привет, Мир!';
Обратите внимание, что CJSCore автоматически передает на клиент необходимые языковые строки в зависимости от текущего языка. Получить к ним доступ можно с помощью JS-функции BX.message.
Перезагрузите страницу, откройте панель инструментов разработчика в браузере и выполните следующий JS-код в консоли:
BX.CustomStuff.helloWorld();
Вы должны увидеть приветственное сообщение.
Важно! Весь JS-код, добавленный с помощью классов CJSCore, Asset или функций AddHeadScript, SetAdditionalCSS, будет объединен в один файл, если это включено в настройках главного модуля. При этом удаление вызова CJSCore::Init не приведет к удалению вашего кода из файла с объединенным кодом. Это значит, что вы не можете управлять загрузкой вашего кода на сторону клиента путем вызова или не вызова CJSCore::Init. Следует применять другой подход.
В custom_stuff.js следует лишь объявить все необходимые функции и классы, которые вам понадобятся для решения задачи (например, «добавить кнопку», «показать диалог подтверждения»).
Если же необходим запуск каких либо функций при загрузке страницы, то следует добавить на страницу еще один небольшой скрипт, который это сделает. Добавить этот скрипт можно с помощью метода Asset::addString (на замену AddHeadString). Он не будет объединен с другим JS-кодом, таким образом, вы можете контролировать запуск кода из custom_stuff.js со стороны сервера.
Например, чтобы метод helloWorld автоматически вызывался после загрузки каждой страницы, нужно сделать следующее:
$asset = Asset::getInstance(); $asset->addString('BX.ready(function () < BX.CustomStuff.helloWorld(); >);');
Теперь рассмотрим несколько примеров.
Пример 1. Кнопка «поблагодарить сотрудника» на странице профиля
[ пример на вебинаре ]
На странице профиля есть небольшой блок действий. Добавим в него пункт «Поблагодарить сотрудника», вот сюда

Для начала добавим в custom_stuff.js функцию, которая создает кнопку.
CustomStuff.createThankButton = function() < var panelWidget = BX.findChildByClassName(document, 'user-profile-events',true); var panelCategoryWidget = BX.findChildByClassName(panelWidget, 'user-profile-events-cont', true); var thankButton = BX.create('a', < attrs : < className : 'user-profile-events-item', href : 'jav * ascript:void(0);' >, html : ' ' + BX.message('CUSTOM_STUFF_THANK_BUTTON') >); BX.bind(thankButton, 'click', CustomStuff.showThankPopup); panelCategoryWidget.appendChild(thankButton); >; CustomStuff.showThankPopup = function() <>;
Здесь узел, представляющий кнопку, создается с помощью функции BX.create (тег a с соответствующим текстом). Также к нему сразу привязывается обработчик клика.
С помощью функции BX.findChildByClassName выполняется поиск узла DOM-дерева — блока действий на странице профиля, а, затем, в нем выполняется поиск контейнера (группы действий). Мы берем первый найденный контейнер и добавляем в него созданную кнопку с помощью метода appendChild.
Теперь добавим вызов написанной функции на странице профиля.
$profileTemplates = array( 'profile' => ltrim(Option::get('intranet', 'path_user', '', SITE_ID), '/') ); if (CComponentEngine::parseComponentPath('/', $profileTemplates, $arVars) == 'profile') < $asset->addString('BX.ready(function () < BX.CustomStuff.createThankButton(); >);'); >
Здесь мы получаем шаблон пути (ЧПУ) к странице профиля из настроек модуля «Интранет» с помощью Option::get, а затем проверяем соответствие текущего URL данному шаблону с помощью CComponentEngine::parseComponentPath.
Посмотрим, что получилось.

Теперь реализуем обработчик клика по этому пункту. Выведем всплывающее окно с полем ввода текста.
CustomStuff.showThankPopup = function() < if (CustomStuff.thankPopup) < CustomStuff.thankPopup.close(); CustomStuff.thankPopup.destroy(); >CustomStuff.thankPopup = new BX.PopupWindow('thank', null, < width : 600, height : 400, closeByEsc : true, closeIcon : true, overlay : < opacity : 50, backgroundColor : '#000' >, titleBar : BX.message('CUSTOM_STUFF_POPUP_TITLE'), content : BX.create('div', < html : '' + BX.message('CUSTOM_STUFF_POPUP_DESCR') + '
' >), buttons : [ new BX.PopupWindowButton( < text : BX.message('CUSTOM_STUFF_POPUP_BUTTON'), className : 'popup-window-button-accept', events : < click : CustomStuff.helloWorld >>) ] >); CustomStuff.thankPopup.show(); >;
На случай двойного клика по нашей кнопке мы убеждаемся, что нет открытых всплывающих окон (если есть — закрываем и уничтожаем). Затем создаем новое окно и выводим его.
Про параметры всплывающего окна можно узнать из записи вебинара.
Посмотрим, что получилось.

На событие клика по кнопке «Отправить начальнику» запускается функция helloWorld. При выполнении реальной задачи, вы, например, могли бы сделать AJAX-запрос, который выполняет настоящую отправку сообщения.
Пример 2. Создание документа на диске из шаблона
[ пример на вебинаре ]
При нажатии на кнопку «Создать документ» в диске появляется окно, в котором можно выбрать, создать документ на компьютере или в облачном сервисе. Добавим в это окно выбор шаблона документа.

В данном случае мы не можем добавить нужную верстку сразу после загрузки страницы, т. к. всплывающее окно появляется в DOM-дереве в момент его открытия. В этом случае мы можем проверить, существуют ли какие-нибудь события, связанные с открытием этого окна.
Выполните в консоли браузера следующий код.
// Лог событий. var originalBxOnCustomEvent = BX.onCustomEvent; BX.onCustomEv ent = function(eventObject, eventName, eventParams, secureParams) < var logData = < eventObject : eventObject, eventName : eventName, eventParams : eventParams, eventParamsClassNames : [], secureParams : secureParams >; for ( var i in eventParams) < var param = eventParams; if (param !== null && typeof param == 'object' && param.constructor) < logData['eventParamsClassNames'].push(param.constructor.name); >else < logData['eventParamsClassNames'].push(null); >> console.log(logData); originalBxOnCustomEvent.apply(null, [ eventObject, eventName, eventParams, secureParams ]); >;
Теперь нажмите кнопку «Создать документ». В консоли браузера должно появиться следующее.

Значит, существуют события, связанные со всплывающим окном, одним из которых мы воспользуемся.
На самом деле фрагмент DOM-дерева для всплывающего окна будет готов уже к моменту onPopupWindowIsInitialized. В целях демонстрации мы подпишемся на событие onAfterPopupShow, чтобы добавить верстку для выбора шаблона.
Создадим функцию в custom_stuff.js, которая регистрирует обработчик события onAfterPopupShow с помощью функции BX.addCustomEvent.
CustomStuff.enableDiskTemplates = function() < BX.addCustomEvent('onAfterPopupShow', CustomStuff.addTemplatesToPopup); >;
Теперь реализуем обработчик события — функцию CustomStuff.addTemplatesToPopup.
/** * @param * popup */ CustomStuff.addTemplatesToPopup = function(popup) < if (popup.uniquePopupId != 'bx-disk-create-file') < return; >if (popup.templatesAdded) < return; >BX.ajax.get('/local/tools/custom_stuff/disk_templates.php', < sessid : BX.bitrix_sessid() >, function(response) < var diskContentDiv = BX.findChildByClassName(popup.contentContainer, 'bx-disk-popup-content', true); BX.adjust(diskContentDiv, < style : < 'padding-bottom' : 0, 'padding-top' : 0 >>); var templatesDiv = BX.create('div', < html : response >); popup.contentContainer.appendChild(templatesDiv); >); popup.templatesAdded = true; >;
Обратите внимание, что обработчик события onAfterPopupShow будет вызываться при каждом открытии любого всплывающего окна. Поэтому в самом начале мы проверяем, обрабатываем ли мы открытие окна создания документа или нет. Узнать ID всплывающего окна можно из лога событий.

На этот раз HTML-код выбора шаблона довольно объемный. Получим его с сервера с помощью AJAX. Мы используем функцию BX.ajax.get, чтобы выполнить запрос.
Важно! Не забывайте передавать параметр sessid и проверять его в обработчике запроса. Это необходимо для предотвращения некоторых атак.
Полученный код добавим во всплывающее окно. Ссылка на узел DOM-дерева хранится в поле contentContainer объекта всплывающего окна.
В целях демонстрации обработчик AJAX-запроса просто отдает верстку для шаблонов. При решении реальной задачи будет уместно вызвать компонент, генерирующий эту верстку.
Осталось сделать запускающий скрипт. Поскольку код на клиенте проверяет, открывается ли окно создания документа или другое. Значит мы можем подписываться на событие открытия окна на любой странице. Поэтому просто будем выполнять следующий код на каждом хите.
$asset->addString( 'BX.ready(function () < BX.CustomStuff.enableDiskTemplates(); >);' );
Теперь при открытии окна создания документа выводится список шаблонов.

Пример 3. Дополнительные поля в карточках ранней версии канбана
[ пример на вебинаре ]
Не так давно данный пример стал устаревшим, т. к. в канбане появились события. Тем не менее, описываемый подход полезно рассмотреть, на случай, если вы попадете в ситуацию, когда части страницы строятся динамически, а событий, за которые можно «зацепиться» нет. Например, при доработке свежей функциональности.
Весь интерфейс канбана строится на стороне клиента с помощью JS. В этом легко убедиться, отключив выполнение JS в браузере. Перед нами стоит задача добавления поля в карточку канбана.
Прежде чем переходить к «грубым» хакам, рассмотрим пример того, как можно дождаться появления на странице карточек, а затем выполнить свой код.
Реализуем функцию, которая выполняется через равные промежутки времени и проверяет наличие нужного нам элемента в DOM-дереве.
CustomStuff.extendKanbanOnFirstLoad = function() < if (CustomStuff.kanbanTimer >0) < return; >CustomStuff.kanbanTimer = setInterval(function() < var mainKanbanDiv = BX.findChildByClassName(document, 'main-kanban', true); if (mainKanbanDiv) < clearInterval(CustomStuff.kanbanTimer); CustomStuff.addHelloWorldToKanban(); >>, 100); >;
Таким образом, когда сетка канбана появится на странице, будет выполнена функция CustomStuff.addHelloWorldToKanban.
Существует и другой метод ожидания элемента DOM-дерева: с помощью MutationObserver.
Теперь реализуем функцию, которая добавит «Hello World!» в каждую карточку.
CustomStuff.addHelloWorldToKanban = function() < var kanbanCards = BX.findChildrenByClassName(document, 'main-kanban-item', true); for ( var cardIndex in kanbanCards) < var date = BX.findChildByClassName(kanbanCards[cardIndex], 'crm-kanban-item-date', true); var helloWorld = BX.create('span', < text : 'Hello World!' >); BX.insertAfter(helloWorld, date); > >;
Функцию CustomStuff.extendKanbanOnFirstLoad будем вызывать, когда открывается любая страница раздела канбана лидов.
if (CSite::InDir('/crm/lead/kanban/')) < $asset->addString( 'BX.ready(function () < BX.CustomStuff.extendKanbanOnFirstLoad();'.'>); '); >
Посмотрим, что получилось.

Также нужно учитывать, что канбан имеет свойство обновлять свое состояние при изменениях на сервере. Например, при добавлении нового лида, его карточка появится без перезагрузки страницы. Чтобы дополнительные поля появились и в ней, момент ее добавления также придется обработать тем или иным образом.
Пример 4. Подтверждение на получение публичной ссылки в диске
[ пример на вебинаре ]
Существуют задачи, которые предыдущим способом делать либо дорого, либо вообще не возможно.

JS — особенный язык В нем позволяется заменить любую функцию или метод на свою реализацию.
Например, в контекстном меню объекта диска есть пункт «Получить публичную ссылку». Никаких событий при этом не происходит. Рассмотрим обработчик события клика по этому пункту меню.
BX.Disk['FolderListClass_p7T8Vm'].openExternalLinkDetailSettingsWithEditing(46);
Видим, что у некоторого объекта вызывается метод openExternalLinkDetailSettingsWithEditing, который создает публичную ссылку и показывает ее во всплывающем окне. Мы хотим запросить подтверждение на получение ссылки перед тем, как она будет показана. Для этого нам не надо знать реализацию метода получения ссылки. Мы заменим оригинальный метод на свой, который будет сначала запрашивать подтверждение, а потом просто вызывать оригинал.
Прежде всего нам нужно узнать, к какому классу относится метод и какая у него сигнатура.
Название класса поможет узнать следующий код, который нужно выполнить в консоли.
BX.Disk['FolderListClass_p7T8Vm'].constructor.name // Вернет "FolderListClass"

Далее можно сделать поиск по коду и узнать, что полное имя класса (с пространством имен) будет BX.Disk.FolderListClass. Ну или интуицию включить
Далее необходимо найти сигнатуру метода, который мы хотим заменить, чтобы узнать, какие аргументы он принимает. Для этого нужно открыть исходный код этого класса.
FolderListClass.prototype.openExternalLinkDetailSettingsWithEditing = function (objectId)
Теперь мы можем просто присвоить BX.Disk.FolderListClass.prototype.openExternalLinkDetailSettingsWithEditing новую версию метода. Напишем для этого функцию в custom_stuff.js.CustomStuff.overrideDiskShare = function() < if (!BX.Disk || !BX.Disk.FolderListClass) < return; >var originalMethod = BX.Disk.FolderListClass.prototype.openExternalLinkDetailSettingsWithEditing; BX.Disk.FolderListClass.prototype.openExternalLinkDetailSettingsWithEditing = function( objectId) < var self = this; CustomStuff.showShareConfirmationDialog(function() < originalMethod.apply(self, [ objectId ]) >); >; >;Осталось реализовать функцию, которая выводит запрос на подтверждение действия.
CustomStuff.showShareConfirmationDialog = function(onAgree) < var confirmationPopup = new BX.PopupWindow('shareConfirmation', null, < width : 400, height : 100, closeByEsc : true, closeIcon : true, overlay : < opacity : 50, backgroundColor : '#000' >, titleBar : BX.message('CUSTOM_STUFF_SHARE_CONFIRMATION_TITLE'), content : BX.create('div', < html : BX.message('CUSTOM_STUFF_SHARE_CONFIRMATION') >), buttons : [ new BX.PopupWindowButton( < text : BX.message('CUSTOM_STUFF_POPUP_BUTTON_YES'), className : 'popup-window-button-accept', events : < click : function() < confirmationPopup.close(); confirmationPopup.destroy(); onAgree(); >> >), new BX.PopupWindowButton( < text : BX.message('CUSTOM_STUFF_POPUP_BUTTON_NO'), events : < click : function() < confirmationPopup.close(); confirmationPopup.destroy(); >> >) ] >); confirmationPopup.show(); >;CustomStuff.overrideDiskShare сама проверяет существование класса на клиенте, поэтому вызовем ее на каждой странице.
$asset->addString( 'BX.ready(function () < BX.CustomStuff.overrideDiskShare(); >);' );Посмотрим, что получилось.
Теперь, если нажать на этот пункт меню, появится всплывающее окно для подтверждения. Публичная ссылка появится только если нажать «Да».
Бонус: работа с боковой панелью-слайдером
[ пример на вебинаре ]В последнее время все чаще используется панель-слайдер в интерфейсе КП. Например, при создании задачи, открытии карточки CRM и т. п.
Дело в том, что клик по кнопке, которая открывает слайдер, обрабатывается не на этапе всплытия, а на этапе перехвата, при чем на элементе html. Это значит, что если понадобится выполнить какой-то код перед открытием слайдера, обработчик клика уже не подойдет.
В данном примере мы сделаем окно с подтверждением при создании новой группы соц. сети.
Открытие страницы в слайдере сопровождается событием, на которое мы подпишем свой обработчик и воспользуемся функцией отмены открытия страницы.
CustomStuff.enableCreateGroupConfirmation = function() < BX.addCustomEvent('SidePanel.Slider:onOpen', CustomStuff.showCreateGroupConfirmation); >; CustomStuff.showCreateGroupConfirmation = function(event) < var slider = event.getSlider(); if (!slider.getUrl().endsWith('/groups/create/')) < return; >if (CustomStuff.isConfirmingGroupCreate) < CustomStuff.isConfirmingGroupCreate = false; >else < event.denyAction(); CustomStuff.showGroupCreateConfirmationDialog(function() < BX.SidePanel.Instance.open(slider.getUrl(), slider.options); >); CustomStuff.isConfirmingGroupCreate = true; > >;Определить, что в данный момент открывается именно страница создания группы можно только по URL. Далее, используем event.denyAction(), чтобы остановить открытие страницы в слайдере и вызываем окно подтверждения. Когда согласие будет получено, еще раз запускаем открытие страницы в слайдере с помощью BX.SidePanel.Instance.open(. ), но на этот раз не останавливаем открытие.
Код всплывающего окна почти не отличается от предыдущего примера.
CustomStuff.showGroupCreateConfirmationDialog = function(onAgree) < var confirmationPopup = new BX.PopupWindow('groupCreateConfirmation', null, < width : 400, height : 100, closeByEsc : true, closeIcon : true, overlay : < opacity : 50, backgroundColor : '#000' >, titleBar : BX.message('CUSTOM_STUFF_GROUP_CREATE_CONFIRMATION_TITLE'), content : BX.create('div', < html : BX.message('CUSTOM_STUFF_GROUP_CREATE_CONFIRMATION') >), buttons : [ new BX.PopupWindowButton( < text : BX.message('CUSTOM_STUFF_POPUP_BUTTON_YES'), className : 'popup-window-button-accept', events : < click : function() < onAgree(); confirmationPopup.close(); confirmationPopup.destroy(); >> >), new BX.PopupWindowButton( < text : BX.message('CUSTOM_STUFF_POPUP_BUTTON_NO'), events : < click : function() < confirmationPopup.close(); confirmationPopup.destroy(); >> >) ], events : < onPopupClose : function() < CustomStuff.isConfirmingGroupCreate = false; >> >); confirmationPopup.show(); >;Теперь при нажатии кнопки «Создать» на странице групп, сначала появляется такое окно.
Также, иногда бывает полезно узнать, открывается ли текущая страница в слайдере или нет. В этом случае достаточно посмотреть на параметр запроса IFRAME. Он будет равен Y, если страница открывается в слайдере.
$context = Context::getCurrent(); $request = $context->getRequest(); $isInSlider = $request->get('IFRAME') == 'Y';Кстати, да, в слайдерах находится iframe, в котором и открываются все страницы.
-----
В комментариях пишите ваши подходы в кастомизации коробки, решения. А так же какие еще темы вы хотели бы видеть на наших вебинарах.
Материалы: исходный код , запись вебинара .
Автор статьи: Никита Калинин , компания Интерволга .




