#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(); }); }); }
Комментариев нет:
Отправить комментарий