In-Portal

Содержание

  • 1. Настройка системы
  • 2. Структура приложения
  • 3. Компоненты
  • 4. Интерфейс административной консоли
    • 4.1. Работа с шаблонами и блоками
    • 4.2. Работа с формами
    • 4.3. Работа со списками
    • 4.4. JavaScript классы
      • 4.4.1. AjaxDropdownPreloader
      • 4.4.2. DropDownMapper
        • Параметры инициализации
        • Настройка шаблона редактирования
        • Настройка обработчика событий
  • 5. База данных
  • 6. Темы и шаблоны
  • 7. Система почтовых извещений
  • 8. Кеширование
  • 9. Отладка приложения
  • 10. Дополнения
  • 11. Структура документации

Приложения

  • Описание событий
  • Описание тэгов
  • Структура таблиц
In-Portal
  • 4. Интерфейс административной консоли
  • 4.4. JavaScript классы
  • 4.4.2. DropDownMapper
  • Редактировать на GitHub

4.4.2. DropDownMapper

Data Source

В статье о JavaScript классе AjaxDropdownPreloader, рассматривалось взаимодействие между двумя выпадающих меню (далее ВМ):

  • первое ВМ - главное;

  • второе ВМ - зависимое.

По мере необходимости возможно подключить любое количество зависимых ВМ, причем каждое новое зависимое ВМ означает создание нового объекта класса AjaxDropdownPreloader. Сложность кода будет расти и логика становиться менее прозрачной. В результате выгода от использования AjaxDropdownPreloader становится спорной.

Класс AjaxDropdownPreloader является оптимальным решением только в случае использования с двумя ВМ (главным - зависимым). А рассматриваемый в данной статье JavaScript класс DropDownMapper специально создан для реализации связи между тремя и более ВМ. Класс DropDownMapper реализует связь между множеством ВМ, используя массив экземпляров класса AjaxDropdownPreloader.

Параметры инициализации

Для успешной реализации связи между многими ВМ необходимо создать экземпляр класса DropDownMapper, передав ему параметры, описанные в приведённой ниже таблице.

название

описание

map (object)

Данный параметр представляет из себя JavaScript объект, который определяет связь между ВМ. Сам объект в свою очередь может состоять из объектов следующего вида:

'UniqueKey' : {
    'Field' : 'FieldName',
    'Pass' : [<field_names>],
    'Value' : 'SelectedValue',
    'Dependent' : false,
    'SubNodes' : { }
}
  • Field (string) - название поля, при изменении значения в котором будут обновлены значения ВМ, указанных в ключе SubNodes;

  • Dependent (boolean) - необязательный параметр, указывающий на то, что данное поле является главным и не от кого не зависит; задаётся только для самого первого поля в объекте в false; отсутствие данного ключа приравнивается к его заданию со значением true;

  • Pass (array) - необязательный параметр, в котором можно указать названия дополнительных полей, значения которых нужно передать в запрос на получение новых опций для данного поля;

  • Value (mixed) - необязательный параметр, в котором можно указать то значение, которое всегда должно выбираться в этом ВМ после подгрузки в него опций;

  • SubNodes (object) - JavaScript объект, содержащий список JavaScript объектов, зависимых от данного поля (вложенность не ограничена); структура каждого из объектов идентична структуре приведённой выше;

Примечание

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

request (string)

Ссылка, при заходе на которую будет возвращён XML документ, содержащий новый набор опций для зависимого ВМ. XML документ должен быть в следующем формате:

<field_options>
    <option>ID1</option>
    <option>ID2</option>
</field_options>

Стоит обратить особое внимание на то, что XML документ содержит только ID опций (без текста, который будет виден в зависимом ВМ). Для того, чтобы у опций был и текст нужно изначально заполнить зависимый ВМ всеми возможными опциями. Обычно установка kOptionsFormatter форматера на это поле является вполне достаточным.

input_mask (string)

Маска для получения любого элемента ввода на форме. Обычно маска получается путём вызова тэга InputName со значением #FIELD_NAME# в качестве названия поля объекта:

<inp2:prefix_InputName field="#FIELD_NAME#"/>
// вернёт строку вида: prefix[ID][#FIELD_NAME#]

Настройка шаблона редактирования

Для подключения класса DropDownMapper на форму достаточно получить его экземпляр с правильно переданными параметрами, в одном из которых и нужно определить зависимость между множеством ВМ. Для примера рассматривается ситуация, в которой ВМ от полей Field_11 и Field_12 зависят от значения поля Field_1, а ВМ Field_111 зависит от значения поля Field_11.

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

  • Добавить на форме элементы ВМ:

<inp2:m_RenderElement name="inp_edit_options" prefix="sample-prefix" field="Field_1" title="la_fld_Field_1"/>
<inp2:m_RenderElement name="inp_edit_options" prefix="sample-prefix" field="Field_11" title="la_fld_Field_11"/>
<inp2:m_RenderElement name="inp_edit_options" prefix="sample-prefix" field="Field_12" title="la_fld_Field_12"/>
<inp2:m_RenderElement name="inp_edit_options" prefix="sample-prefix" field="Field_111" title="la_fld_Field_111"/>
  • Добавить вызов класса DropDownMapper передав ему все требуемые параметры:

var $mapping = {
    'Level_1' : {
        'Field' : 'Field_1',
        'Dependent' : false,
        'SubNodes' : {
            'Level_11' : {
                'Field' : 'Field_11',
                'SubNodes' : {
                    'Level_111' : { 'Field' : 'Field_111' }
                }
            },

            'Level_12' : {
                'Field' : 'Field_12'
            }
        }
    }
};

new DropDownMapper(
    $mapping,
    '<inp2:m_Link template="dummy" pass="m,sample-prefix" sample-prefix_event="OnGetDropDownXML" q="#QUESTIONED#" f="#FILTERS#" no_amp="1"/>',
    '<inp2:sample-prefix_InputName field="#FIELD_NAME#"/>'
);

Настройка обработчика событий

В метод OnGetDropDownXML необходимо добавить функциональность для получения опций ВМ каждого конкретного случая:

/**
 * [AJAX] Метод для получения отфильтрованных опций в виде XML документа.
 *
 * @param kEvent $event
 */
function OnGetDropDownXML(&$event)
{
    $event->status = erSTOP;

    if ($this->Application->GetVar('ajax') != 'yes') {
        return ;
    }

    // $q поле соответствующие зависимому ВМ, для которого в данный момент вычисляются опции.
    $q = $this->Application->GetVar('q');

    $f = $this->Application->GetVar('f');
    parse_str($f, $filters);
    // $filters массив, где ключи это поля соответствующих ВМ, а значения выбранные опции из соответствующих ВМ

    // Все необходимые фильтры для SQL запроса в массиве $filters
    // Ниже требуется составить SQL для каждого конкретного случая
    switch ($q) {
        case 'Field_12':
            $sql = 'SELECT ...
                    FROM ...
                    WHERE ...';
            break;

        case 'Field_11':
            $sql = 'SELECT ...
                    FROM ...
                    WHERE ...';
            break;

        case 'Field_111':
            $sql = 'SELECT ...
                    FROM ...
                    WHERE ...';
            break;
    }

    if (!$sql) {
        return ;
    }

    $data = $this->Conn->Query($sql);


    if (!$data) {
        return ;
    }

    $o = '';
    foreach ($data as $row) {
        $attributes = '';
        foreach ($row as $field => $value) {
            if ($field == 'Value' || $field == 'Name') {
                continue;
            }

            $attributes .= $field . '="' . htmlspecialchars($value) . '" ';
        }

        $o .= '<option value="' . htmlspecialchars($row['Value']) . '" ' . $attributes  .'><![CDATA['  . $row['Name'] . ']]></option>';
    }

    $this->Application->XMLHeader();
    echo '<field_options>' . $o . '</field_options>';
}

Событие OnGetDropDownXML необходимо добавить в метод mapPermissions, который обеспечит проверку наличия у пользователя необходимых прав доступа для вызова данного события:

/**
 * Метод связывающий события и права, необходимые для их выполнения.
 *
 */
function mapPermissions()
{
    parent::mapPermissions();
    $permissions = Array (
        'OnGetDropDownXML' => Array ('self' => true),
    );

    $this->permMapping = array_merge($this->permMapping, $permissions);
}

Совет

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

  • В начале события рекомендуется установить статус его выполнения в erSTOP. Это укажет на то, что по окончания выполнения события не нужно показывать содержание переданного шаблона (в данном случае это dummy):

$event->status = erSTOP;
  • В начале события написать код, который позволит игнорировать запросы, которые будут делать поисковые системы:

if ($this->Application->GetVar('ajax') != 'yes') {
    return ;
}

Параметр ajax добавляется автоматически при отправлении каждого AJAX запроса. Если поисковая система где-то найдёт ссылку, в которой указано данное событие, то зайдя на неё тело события выполнено не будет.

  • Перед выводом XML документа на экран необходимо послать браузеру соответствующий заголовок. Сделать это можно при помощи метода Application::XMLHeader:

$this->Application->XMLHeader();

См. также

  • AjaxDropdownPreloader

Предыдущая Следующая

© Авторские права 1997, In-Portal.

Собрано при помощи Sphinx с использованием темы, предоставленной Read the Docs.