Страницы

Поиск по вопросам

пятница, 24 января 2020 г.

Как в обработчике blur дождаться окончания обработки в focus

#jquery #angularjs #blur #focus


Возникла проблема с созданием datepicker для поля даты. На поле висит 2 обработчика
- blur и focus, в focus создается datepicker, в blur он удаляется. Причем в focus он
создается с помощью deferred объекта.

.directive('datePicker', [ '$compile', '$document', 'datePickerService', '$templateRequest',
function ($compile, $document, datePickerService, $templateRequest) { 
    function link(scope, element, attrs) {
            var picker = null;
                var $elementFocusProcessing = $.Deferred();
                element.on('focus', function (event) {
                    populatelimits();
                    prepareViewData();
                    var pos = angular.extend(element.offset(), { height: element[0].offsetHeight
});                    

                    $templateRequest(datePickerService.datePickerTemplate).then(function
(html) {
                        var template = angular.element(html);
                        $document.find('body').append(template);
                        picker = $compile(template)(scope);
                        picker.css({ top: pos.top + pos.height + 5, left: pos.left,
display: 'block', position: 'absolute' });

                        picker.on('mousedown', function (evt) {
                            evt.preventDefault();
                        });
                        $elementFocusProcessing.resolve();
                    });
                });

                element.on('blur', function () {
                    $elementFocusProcessing.then(function () {
                        if (picker) {
                            picker.remove();
                            picker = null;
                        };
                        $elementFocusProcessing = $.Deferred();
                    });
                });
            }

        return {
            restrict: 'A',
            link: link,
            scope : {
                model: '=ngModel'
            }
        };


И собственно проблема: если выделить поле даты, потом переключиться на другое окно,
а затем кликнуть на любое место страницы, кроме поля даты, возникают подряд несколько
событий: focus поля, blur поля, click по странице. При этом создание picker в focus
завершается позже, чем попытка его удаления в blur, и он не удаляется, хотя фокус элемента
в тоге оказывается потерян. Как сделать так, чтобы выполнение кода в blur происходило
только после завершения выполнения кода в focus? Мне пока пришло в голову только сделать
дополнительную переменную focusEnded для определения того, идет ли выполнение кода
в focus, а в blur организовать цикл с таймаутом, но чувствую, что можно более изящно
сделать это с использованием deferred объектов.
    


Ответы

Ответ 1



Так как рабочего примера нет, можно рассуждать только теоретически: Так как шаблон не меняется, его не нужно подгружать не только на каждый фокус, но и на каждый link. Следовательно, его можно вынести из функции и результат, а он является promise, сохранить в переменной: var templatePromise = $templateRequest(datePickerService.datePickerTemplate); Далее, функция link, внутри нее подразумеваем, что шаблон уже подгрузился, для этого все остальное делаем в обработчике success функции then у нашего сохраненного templatePromise function link(scope,element,attrs){ templatePromise.then(function(html){ //достаточно сделать всего один элемент, // который мы будем добавлять или удалять var template = angular.element(html); //и добавим событие, чтобы не добавлять его каждый раз //так как template это уже объект jqLite можно сделать так template.on('mousedown', function (evt) { evt.preventDefault(); } ); //добавляем on focus element.on('focus', function (event) { ... $document.find('body').append(template); $compile(template)(scope); //так как template это объект jqLite, то вместо picker можно использовать его template.css(...) ... }); //добавляем on blur element.on('blur', function () { //так как добавляли template, то и удалять можно его //а так как он у нас всегда есть, то не надо проверять на null template.remove(); }); }); }

Комментариев нет:

Отправить комментарий