X-editable и Select2. Часть 2

x-editable select2Подгрузку данных по ajax с кешированием мы решили ранее (часть первая).

Осталось еще несколько неудобных моментов.
Во-первых: сам факт выбора пункта в выпадающем списке уже является подтверждением желания заменить исполнителя на выбранного, кнопа «сохранить» на плашке нам не нужна.
Во-вторых: Плашка закрывается кликом на любом месте вне плашки и по нажатию на Esc. Кнопа «Закрыть» тоже не нужна.
Ну, с этим вроде просто, добавляем 2 строчки в конфигурацию:

cell.editable({
    ...
    showbuttons : false,
    saveonchange : true,
    ...
});

В третьих: Select должен открываться автоматически при появлении плашки. Совершенно ни к чему заставлять человека делать лишние бессмысленные клики. Раз кликнули для редактирования, список должен быть виден незамедлительно. Фокус должен быть установлен в поле для поиска при достаточном количестве результатов.

На вопрос — как это сделать? — мануал ответа не дал. Значит будем решать проблему подручными средствами. Выясняем селектор, однозначно указывающий на select2 в появившейся плашке и даем команду на открытие сразу же после команды cell.editable(‘show’);

elem.editable('show');
$('.editable-popup:visible input[type=hidden]').select2('open');

double droplist
Тестируем. Хмм… вот это глюк!
При клике вне плашки и попытке смены исполнителя для другой записи появляется аж 2 списка, один, как положено из select на плашке, а второй на месте, где открывался только что закрывшийся список. и Курсор мерцает между двумя полями поиска. Выглядит ужасно!
select2 drop in sourceСмотрим, что там в исходном коде: вот и наши 2 списка. Один из них от уже исчезнушей плашки.
Может удалить старый выпадающий список перед тем как показывать новый?

$('.select2-drop').remove();
elem.editable('show');
$('.editable-popup:visible input[type=hidden]').select2('open');

Вот это прикол! Нифига не изменилось! По прежнему вылезает 2 списка. Что-то реанимирует уже удаленный список. Получается, что на момент открытия новой плашки редактирования старый select2 еще жив и в процессе скрытия плашки редактирования от предыдущей записи выпадающий список для нее восстанавливается, прежде, чем select2 пропадет из кода страницы. То есть какое-то время на странице существует 2 разных select2 в контейнерах с классом editable-popup, причем оба контейнера находятся на странице и оба еще видимы уже после открытия второго.
Есть смысл дать некоторую задержку по времени перед открытием нового выпадающего списка. Начнем с задержки 200 мс, думаю, что 100 может быть недостаточно и при этом 200 мс все еще практически неощутимая задержка.

elem.editable('show');
window.setTimeout(function() {
    $('.editable-popup:visible input[type=hidden]').select2('open');
}, 200);

Отлично! От глюка избавились.
Осталась последняя хотелка: по какой-то причине select2 появляется с пустым значением, а должен появиться с выбранным текущим исполнителем. Чтобы для снятия исполнителя достаточно было кликнуть по крестику очистки.
То есть перед .select2(‘open’) нам надо отыскать id выбранного исполнителя в массиве App.cache.empls и задать значение для списка — .select2(‘val’, id)
Финальный код инициализации редактирования:

$('.dataTable a.x-edit-select2').click(function() {
    // инициализацию и вызов плашки 
    // редактирования лучше вынести 
    // в отдельную функцию, чтобы не дублировать код
    // для инициализации в случаях, когда список
    // запрашивается и когда уже закеширован
    function showEditForm() {
        // инициализируем editable только 
        // один раз для ячейки
        if (!cell.data('source-setted')) {
            cell.editable({
                url : '/tasks/edit-field/',
                type : 'select2',
                inputclass : 'form-control input-medium',
                toggle : 'manual',
                source : App.cache.empls,
                emptytext : '',
                showbuttons : false,
                saveonchange : true,
                select2 : {
                    minimumResultsForSearch : 7,
                    placeholder : 'Выберите исполнителя',
                    allowClear : true
                }
            });
            cell.data('source-setted', true);
        }
        cell.editable('show');
        window.setTimeout(function() {
            var text, id;
            text = elem.text();
            for (var i in App.cache.empls) if (App.cache.empls[i].text == text) {
                id = App.cache.empls[i].id;
                break;
            }
            $('.editable-popup:visible input[type=hidden]').select2('val', id).select2('open');
        }, 200);
    }
    var cell = $(this);
    // чтобы не загаживать глобальное пространство имен, 
    // все свое пакуем в объект App
    // проверяем объявлен ли он уже
    if (typeof App == 'undefined') var App = {};
    if (typeof App.cache == 'undefined') App.cache = {};
    // если списка еще нет
    if (typeof App.cache.empls == 'undefined') {
        cell.addClass('loading');
        url = '/users/autocomplete/empls/';
        $.post(
            url, {},
            function(answ) {
                cell.removeClass('loading');
                answ = App.parseJSON(answ);
                if (answ !== false) App.cache.empls = answ;
                showEditForm(App.cache.empls);
            },
            'text'
        );
    // список уже получен, надо только инициализировать
    // (если необходимо)
    // и открыть плашку редактирования
    } else {
        showEditForm(App.cache.empls);
    }
    return false;
});

Добавить комментарий