Project

General

Profile

Actions

Padrão #31

open

Ajustar diretiva Popover Para Funcionar com campos Select

Added by jean sodré 6 months ago. Updated 6 months ago.

Status:
concluído
Priority:
normal
Assignee:
Category:
-
Start date:
07/09/2025
Due date:
% Done:

0%

Estimated time:

Description

Ajustar diretiva do popover para funcionar com campos select, ao selecionar um campo, aparece o ícone do popover


Related issues 2 (2 open0 closed)

Copied to Padrão #33: Checkbox diretiva hover e clickconcluídojean sodré07/09/2025

Actions
Copied to Padrão #34: Ajustar diretiva de select para permitir desabilitar opções, dependendo da seleção do usuárioconcluídojean sodré07/09/2025

Actions
Actions #1

Updated by jean sodré 6 months ago

  • Status changed from a fazer to em execução
Actions #2

Updated by jean sodré 6 months ago · Edited

  • Status changed from em execução to teste

Segue o código completo da diretiva do popover:

.directive('contextualPopover', function($document, $window, $timeout) {
    return {
        restrict: 'E',
        transclude: true,
        scope: {
            title: '@',
            show: '=',
            trigger: '@',
            width: '@',
            iconTarget: '@',
            obrigatorio: '@',
            watchModel: '=?',           // Modelo a ser observado
            triggerValue: '@?',         // Valor que dispara o popover
            triggerValues: '=?',        // Array de valores que disparam o popover
            customSelectTarget: '@?'    // ID do custom-select alvo
        },
        template: `
            <div class="popover-container {{getObrigatorioClass()}}" 
                 ng-show="show" 
                 ng-style="getPopoverStyle()" 
                 ng-click="preventClose($event)"
                 ng-mouseenter="onMouseEnterPopover()"
                 ng-mouseleave="onMouseLeavePopover()">
                <div class="popover-content">
                    <div class="popover-tag {{getTagClass()}}">
                        {{getTag()}}
                    </div>
                    <div class="popover-body" ng-transclude></div>
                    <div class="popover-footer footer-saved">
                        <span style="color: #bdbdbd">
                            Salvamento Automático
                        </span>
                        <span class="flex align-items">
                            <svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px" fill="#0A8754"><path d="m429-336 238-237-51-51-187 186-85-84-51 51 136 135Zm51 240q-79 0-149-30t-122.5-82.5Q156-261 126-331T96-480q0-80 30-149.5t82.5-122Q261-804 331-834t149-30q80 0 149.5 30t122 82.5Q804-699 834-629.5T864-480q0 79-30 149t-82.5 122.5Q699-156 629.5-126T480-96Zm0-72q130 0 221-91t91-221q0-130-91-221t-221-91q-130 0-221 91t-91 221q0 130 91 221t221 91Zm0-312Z"/></svg>
                            Salvo
                        </span>
                    </div>
                </div>
            </div>
        `,
        link: function(scope, element) {
            // VARIÁVEIS DE CONTROLE
            let triggerElement = null;
            let editIcon = null;
            let isMouseOverPopover = false;
            let mouseOutTimeout = null;
            let scrollListeners = [];
            let scrollDebounceTimeout = null;
            let scrollPollingInterval = null;
            let lastScrollPositions = {};
            let initialPopoverPosition = null;
            let currentMousePosition = { x: 0, y: 0 };
            let customSelectElement = null; // 
            let isCustomSelectMode = false; // 
            
            // CONFIGURAÇÕES
            const MARGIN = 10;
            const MOUSE_OUT_DELAY = 15000; 
            const PROXIMITY_THRESHOLD = 2; 

            // UTILITÁRIOS DE POPOVER
            scope.preventClose = function(event) {
                event.stopPropagation();
            };

            scope.onMouseEnterPopover = function() {
                clearTimeout(mouseOutTimeout);
                isMouseOverPopover = true;
                console.log('Mouse sobre popover - cancelando timer de fechamento');
            };

            scope.onMouseLeavePopover = function() {
                isMouseOverPopover = false;
                console.log('Mouse saiu do popover - iniciando timer de 15s');
                startMouseOutTimer();
            };

            // CONTROLE DE PROXIMIDADE DO MOUSE
            function updateMousePosition(event) {
                currentMousePosition = {
                    x: event.clientX,
                    y: event.clientY
                };
            }

            function calculateDistance(pos1, pos2) {
                const deltaX = pos1.x - pos2.x;
                const deltaY = pos1.y - pos2.y;
                return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
            }

            function isMouseNearInitialPosition() {
                if (!initialPopoverPosition) return false;
                
                const distance = calculateDistance(currentMousePosition, initialPopoverPosition);
                console.log('Distância do mouse ao ponto inicial:', Math.round(distance), 'px');
                return distance <= PROXIMITY_THRESHOLD;
            }

            function shouldPreventScrollClose() {
                const mouseOverPopover = isMouseOverPopover;
                const nearInitialPosition = isMouseNearInitialPosition();
                
                console.log('Mouse sobre popover:', mouseOverPopover, '| Próximo ao inicial:', nearInitialPosition);
                
                return mouseOverPopover && nearInitialPosition;
            }

            scope.getPopoverStyle = function() {
                let style = scope.position || {};
                if (scope.width) {
                    style.width = scope.width;
                }
                return style;
            };

            scope.getObrigatorioClass = function() {
                return scope.obrigatorio === "true" ? "obrigatorio-popover" : "opcional-popover";
            };

            scope.getTag = function() {
                return scope.obrigatorio === "true" ? "obrigatório" : "opcional";
            };

            scope.getTagClass = function() {
                return scope.obrigatorio === "true" ? "obrigatorio-tag" : "opcional-tag";
            };

            function startMouseOutTimer() {
                clearTimeout(mouseOutTimeout);
                
                if (isMouseOverPopover) {
                    console.log('Mouse ainda sobre popover - não iniciando timer');
                    return;
                }
                
                console.log('Iniciando timer de mouse fora: 15s');
                
                mouseOutTimeout = setTimeout(function() {
                    if (scope.show && !isMouseOverPopover) {
                        console.log('💤 Fechando popover por mouse fora (15s)');
                        scope.$apply(function() {
                            scope.show = false;
                        });
                    }
                }, MOUSE_OUT_DELAY);
            }

            // DETECÇÃO DE SCROLL UNIVERSAL
            function handleScroll(event) {
      
                if (scrollDebounceTimeout) {
                    clearTimeout(scrollDebounceTimeout);
                }
                
                scrollDebounceTimeout = setTimeout(function() {
                    if (!scope.show) {
                        return;
                    }
                    
                    // Verifica se o scroll foi dentro do popover
                    const popoverContainer = element[0].querySelector('.popover-container');
                    const isScrollInsidePopover = popoverContainer && (
                        popoverContainer.contains(event.target) || 
                        popoverContainer === event.target
                    );
                    
                    if (isScrollInsidePopover) {
                        return;
                    }
                    

                    if (shouldPreventScrollClose()) {
                        return;
                    }

                    try {
                        scope.$apply(function() {
                            scope.show = false;
                        });
                    } catch (error) {
                        scope.show = false;
                    }
                }, 1);
            }

            // POLLING DE SCROLL COMO FALLBACK
            function startScrollPolling() {
                if (scrollPollingInterval) {
                    clearInterval(scrollPollingInterval);
                }
                
                // Armazena posições iniciais
                lastScrollPositions = {
                    window: $window.pageYOffset || 0,
                    documentElement: ($document[0].documentElement && $document[0].documentElement.scrollTop) || 0,
                    body: ($document[0].body && $document[0].body.scrollTop) || 0
                };
                
                scrollPollingInterval = setInterval(function() {
                    if (!scope.show) {
                        clearInterval(scrollPollingInterval);
                        scrollPollingInterval = null;
                        return;
                    }
                    
                    const currentPositions = {
                        window: $window.pageYOffset || 0,
                        documentElement: ($document[0].documentElement && $document[0].documentElement.scrollTop) || 0,
                        body: ($document[0].body && $document[0].body.scrollTop) || 0
                    };
                    
                    // Verifica se houve mudança em qualquer posição
                    let scrollDetected = false;
                    for (let key in currentPositions) {
                        const diff = Math.abs(currentPositions[key] - lastScrollPositions[key]);
                        if (diff > 1) { // Threshold de 1px
                            scrollDetected = true;
                            console.log('Polling detectou scroll em:', key);
                            break;
                        }
                    }
                    
                    if (scrollDetected) {
                        // Verifica proximidade do mouse antes de fechar
                        if (shouldPreventScrollClose()) {
                            console.log('Polling: Mouse sobre popover e próximo - mantendo aberto');
                            lastScrollPositions = currentPositions; // Atualiza posições para próxima verificação
                            return;
                        }
                        
                        console.log('Fechando popover por polling');
                        try {
                            scope.$apply(function() {
                                scope.show = false;
                            });
                        } catch (error) {
                            scope.show = false;
                        }
                    }
                    
                    lastScrollPositions = currentPositions;
                }, 50); // Verifica a cada 200ms
            }

            // ADICIONAR LISTENERS DE SCROLL
            function addScrollListeners() {
                console.log('Configurando listeners de scroll');
                
                // Elementos para monitorar
                const elements = [window, document, document.documentElement, document.body];
                
                elements.forEach(function(element, index) {
                    if (element && element.addEventListener) {
                        
                        element.addEventListener('scroll', handleScroll, { 
                            passive: true, 
                            capture: true 
                        });
                        scrollListeners.push({
                            element: element,
                            handler: handleScroll
                        });
                    }
                });
                
                // Listener adicional no documento
                if ($document[0] && $document[0].addEventListener) {
                    $document[0].addEventListener('scroll', handleScroll, { 
                        passive: true, 
                        capture: true 
                    });
                    scrollListeners.push({
                        element: $document[0],
                        handler: handleScroll
                    });
                }
                
                // Adiciona listener para rastrear posição do mouse
                document.addEventListener('mousemove', updateMousePosition, { passive: true });
                scrollListeners.push({
                    element: document,
                    handler: updateMousePosition,
                    type: 'mousemove'
                });
                
                // Inicia polling como fallback
                startScrollPolling();
            }

            // REMOVER LISTENERS DE SCROLL
            function removeScrollListeners() {
              
                
                if (scrollDebounceTimeout) {
                    clearTimeout(scrollDebounceTimeout);
                    scrollDebounceTimeout = null;
                }
                
                if (scrollPollingInterval) {
                    clearInterval(scrollPollingInterval);
                    scrollPollingInterval = null;
                }
                
                scrollListeners.forEach(function(listener, index) {
                    if (listener.element && listener.element.removeEventListener) {
                        const eventType = listener.type || 'scroll';
                        listener.element.removeEventListener(eventType, listener.handler, { capture: true });
                    }
                });
                
                scrollListeners = [];
            }

            // FUNÇÃO PARA LIMPAR TODOS OS TIMERS
            function clearAllTimers() {
                if (mouseOutTimeout) {
                    clearTimeout(mouseOutTimeout);
                    mouseOutTimeout = null;
                }
                
                if (scrollDebounceTimeout) {
                    clearTimeout(scrollDebounceTimeout);
                    scrollDebounceTimeout = null;
                }
                
                if (scrollPollingInterval) {
                    clearInterval(scrollPollingInterval);
                    scrollPollingInterval = null;
                }
            }

            // EVENTOS DE TECLADO (ESC)
            function handleKeyDown(event) {
                if (!scope.show) return;
                
                if (event.keyCode === 27 || event.key === 'Escape') {
                    scope.$apply(function() {
                        scope.show = false;
                    });
                    event.preventDefault();
                    event.stopPropagation();
                }
            }

            function handleClickOutside(event) {
                if (!scope.show) return;
                
                // Verifica se tem custom-select aberto
                if (document.body.hasAttribute('data-custom-select-open')) {
                    console.log('Custom-select aberto - não fechando popover');
                    return;
                }
                
                const popoverContainer = element[0].querySelector('.popover-container');
                
                // Verifica se clicou dentro do popover
                if (popoverContainer && popoverContainer.contains(event.target)) {
                    console.log('Clique dentro do popover - não fechando');
                    return;
                }
                
                // Verifica se clicou no trigger
                if (triggerElement && triggerElement.contains(event.target)) {
                    console.log('Clique no trigger - não fechando');
                    return;
                }
                
                // Verifica se clicou no ícone de edição
                if (editIcon && editIcon.contains(event.target)) {
                    console.log('Clique no ícone - não fechando');
                    return;
                }
                
                // Verifica se clicou em elementos de custom-select
                const customSelectClasses = [
                    'custom-select-wrapper', 'select-header', 'select-options-body', 'option', 'arrow-icon'
                ];
                
                for (let className of customSelectClasses) {
                    if (event.target.classList && event.target.classList.contains(className)) {
                        console.log('Clique em custom-select - não fechando');
                        return;
                    }
                }
                
                if (event.target.closest && (
                    event.target.closest('.custom-select-wrapper') ||
                    event.target.closest('.select-options-body')
                )) {
                    console.log('Clique em elemento filho de custom-select - não fechando');
                    return;
                }
                
                scope.$apply(function() {
                    scope.show = false;
                });
            }

            // CRIAÇÃO E CONTROLE DO ÍCONE DE EDIÇÃO
            function createEditIcon() {
                if (editIcon) return;
                
                editIcon = document.createElement('span');
                editIcon.className = 'popover-edit-icon';

                if (scope.obrigatorio === "true") {
                    editIcon.innerHTML = `
                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
                            <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
                        </svg>
                    `;
                } else {
                    editIcon.innerHTML = `
                        <svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px" 
                            fill="#1f1f1f"><path d="M444-144v-300H144v-72h300v-300h72v300h300v72H516v300h-72Z"/>
                        </svg>
                    `;
                }

                editIcon.title = 'Editar';
                
                if (isCustomSelectMode) {
                    setIconEnabled(true);
                } else {
                    setIconDisabled(true);
                }
                
                editIcon.addEventListener('click', function(e) {
                    e.stopPropagation();
                    e.preventDefault();
                    
                    if (!editIcon.hasAttribute('data-disabled')) {
                        scope.$apply(function() {
                            scope.show = !scope.show;
                            if (scope.show) {
                                $timeout(updatePosition, 10);
                            }
                        });
                    }
                });

                return editIcon;
            }

            function setIconDisabled(disabled) {
                if (!editIcon) return;
                
                if (disabled) {
                    editIcon.setAttribute('data-disabled', 'true');
                    editIcon.title = 'Marque a opção para editar';
                    editIcon.style.cssText = `
                        display: inline-flex;
                        align-items: center;
                        justify-content: center;
                        width: 20px;
                        height: 20px;
                        cursor: not-allowed;
                        color: #ccc;
                        background: #f5f5f5;
                        border-radius: 3px;
                        border: 1px solid #e0e0e0;
                        margin-left: 8px;
                        transition: all 0.2s ease;
                        vertical-align: middle;
                        opacity: 0.6;
                    `;
                } else {
                    setIconEnabled(true);
                }
            }

            function setIconEnabled(enabled) {
                if (!editIcon) return;
                
                if (enabled) {
                    editIcon.removeAttribute('data-disabled');
                    editIcon.title = 'Editar';
                    editIcon.style.cssText = `
                        display: inline-flex;
                        align-items: center;
                        justify-content: center;
                        width: 20px;
                        height: 20px;
                        cursor: pointer;
                        color: #666;
                        background: #f8f9fa;
                        border-radius: 3px;
                        border: 1px solid #dee2e6;
                        margin-left: 8px;
                        transition: all 0.2s ease;
                        vertical-align: middle;
                        opacity: 1;
                    `;
                    
                    // Remove eventos anteriores
                    editIcon.removeEventListener('mouseenter', iconMouseEnter);
                    editIcon.removeEventListener('mouseleave', iconMouseLeave);
                    
                    // Adiciona novos eventos
                    editIcon.addEventListener('mouseenter', iconMouseEnter);
                    editIcon.addEventListener('mouseleave', iconMouseLeave);
                }
            }

            function iconMouseEnter() {
                if (!editIcon.hasAttribute('data-disabled')) {
                    editIcon.style.color = '#007bff';
                    editIcon.style.borderColor = '#007bff';
                    editIcon.style.backgroundColor = '#e3f2fd';
                }
            }

            function iconMouseLeave() {
                if (!editIcon.hasAttribute('data-disabled')) {
                    editIcon.style.color = '#666';
                    editIcon.style.borderColor = '#dee2e6';
                    editIcon.style.backgroundColor = '#f8f9fa';
                }
            }

            function toggleIconVisibility(show) {
                if (!editIcon) return;
                
                editIcon.style.display = show ? 'inline-flex' : 'none';
                
                if (show) {
                    setIconEnabled(true);
                } else {
                    scope.show = false;
                }
            }

            function positionEditIconForCustomSelect() {
                if (!editIcon || !customSelectElement) return;
                
                // Encontra o wrapper do custom-select
                const wrapper = customSelectElement.querySelector('.custom-select-wrapper');
                if (wrapper) {
                    if (wrapper.nextSibling) {
                        wrapper.parentNode.insertBefore(editIcon, wrapper.nextSibling);
                    } else {
                        wrapper.parentNode.appendChild(editIcon);
                    }
                }
            }

            function positionEditIcon() {
                if (!editIcon) return;
                
                if (isCustomSelectMode) {
                    positionEditIconForCustomSelect();
                    return;
                }
                
                // Lógica original para trigger normal
                let targetElement = null;
                
                if (scope.iconTarget) {
                    targetElement = document.getElementById(scope.iconTarget);
                }
                
                if (!targetElement && triggerElement) {
                    if (triggerElement.id) {
                        targetElement = document.querySelector(`label[for="${triggerElement.id}"]`);
                    }
                    
                    if (!targetElement) {
                        targetElement = triggerElement;
                    }
                }
                
                if (targetElement) {
                    if (targetElement.nextSibling) {
                        targetElement.parentNode.insertBefore(editIcon, targetElement.nextSibling);
                    } else {
                        targetElement.parentNode.appendChild(editIcon);
                    }
                }
            }

            function showEditIcon() {
                if (!editIcon) {
                    createEditIcon();
                }
                
                positionEditIcon();
                editIcon.style.display = 'inline-flex';
            }

            function removeEditIcon() {
                if (editIcon && editIcon.parentNode) {
                    editIcon.parentNode.removeChild(editIcon);
                    editIcon = null;
                }
            }

            function calculateBestPosition(triggerRect, popoverRect) {
                const viewportWidth = $window.innerWidth;
                const viewportHeight = $window.innerHeight;
                
                const popoverWidth = scope.width ? parseInt(scope.width) : popoverRect.width;
                const popoverHeight = popoverRect.height;
                
                const spaceAbove = triggerRect.top;
                const spaceBelow = viewportHeight - triggerRect.bottom;
                const spaceLeft = triggerRect.left;
                const spaceRight = viewportWidth - triggerRect.right;

                let position = {
                    position: 'fixed',
                    zIndex: '9999'
                };

                // Posição vertical
                if (spaceBelow >= popoverHeight + MARGIN) {
                    position.top = triggerRect.bottom + MARGIN + 'px';
                } else if (spaceAbove >= popoverHeight + MARGIN) {
                    position.top = (triggerRect.top - popoverHeight - MARGIN) + 'px';
                } else {
                    position.top = Math.max(MARGIN, (viewportHeight - popoverHeight) / 2) + 'px';
                }

                // Posição horizontal
                if (spaceRight >= popoverWidth + MARGIN) {
                    position.left = triggerRect.right + MARGIN + 'px';
                } else if (spaceLeft >= popoverWidth + MARGIN) {
                    position.left = (triggerRect.left - popoverWidth - MARGIN) + 'px';
                } else {
                    position.left = Math.max(MARGIN, (viewportWidth - popoverWidth) / 2) + 'px';
                }

                return position;
            }

            function updatePosition() {
                let referenceElement = null;
                
                if (isCustomSelectMode && customSelectElement) {
                    referenceElement = customSelectElement.querySelector('.custom-select-wrapper');
                } else if (triggerElement) {
                    referenceElement = triggerElement;
                }
                
                if (!referenceElement) return;
                
                const triggerRect = referenceElement.getBoundingClientRect();
                const popoverElement = element[0].querySelector('.popover-container');
                if (!popoverElement) return;
                
                const popoverRect = popoverElement.getBoundingClientRect();
                scope.position = calculateBestPosition(triggerRect, popoverRect);
                
                if (!scope.$$phase) {
                    scope.$apply();
                }
            }

            function shouldShowIcon(value) {
                if (!value) return false;
                
                // Verifica se o valor está na lista de valores que disparam
                if (scope.triggerValues && Array.isArray(scope.triggerValues)) {
                    return scope.triggerValues.includes(value);
                }
                
                // Verifica se é o valor específico que dispara
                if (scope.triggerValue) {
                    return value === scope.triggerValue;
                }
                
                return false;
            }
            
            scope.$watch('watchModel', function(newVal, oldVal) {
                if (!isCustomSelectMode) return;
                
                console.log('Modelo do custom-select mudou:', oldVal, '->', newVal);
                
                if (shouldShowIcon(newVal)) {
                    console.log('Valor dispara popover - mostrando ícone');
                    toggleIconVisibility(true);
                } else {
                    console.log('Valor não dispara popover - ocultando ícone');
                    toggleIconVisibility(false);
                }
            });

            // Watcher original para trigger
            scope.$watch('trigger', function(newVal) {
                if (newVal && !isCustomSelectMode) {
                    triggerElement = document.getElementById(newVal);
                    if (triggerElement) {
                        triggerElement.addEventListener('change', function() {
                            scope.$apply(function() {
                                if (triggerElement.checked) {
                                    setIconDisabled(false);
                                } else {
                                    scope.show = false;
                                    setIconDisabled(true);
                                }
                            });
                        });
                        
                        $timeout(function() {
                            showEditIcon();
                            setIconDisabled(!triggerElement.checked);
                        }, 50);
                    }
                }
            });

            scope.$watch('customSelectTarget', function(newVal) {
                if (newVal) {
                    isCustomSelectMode = true;
                    customSelectElement = document.getElementById(newVal);
                    
                    if (customSelectElement) {

                        $timeout(function() {
                            createEditIcon();
                            positionEditIconForCustomSelect();
                            
                            // Verifica valor inicial
                            if (shouldShowIcon(scope.watchModel)) {
                                toggleIconVisibility(true);
                            } else {
                                toggleIconVisibility(false);
                            }
                        }, 100);
                    }
                }
            });

            scope.$watch('show', function(newVal) {
                if (newVal) {

                    // Reset controles
                    isMouseOverPopover = false;
                    
                    // Armazena posição inicial
                    let referenceElement = null;
                    
                    if (isCustomSelectMode && customSelectElement) {
                        referenceElement = customSelectElement.querySelector('.custom-select-wrapper');
                    } else if (triggerElement) {
                        referenceElement = triggerElement;
                    }
                    
                    if (referenceElement) {
                        const triggerRect = referenceElement.getBoundingClientRect();
                        initialPopoverPosition = {
                            x: triggerRect.left + triggerRect.width / 2,
                            y: triggerRect.top + triggerRect.height / 2
                        };
                        
                    }
                    
                    // Adiciona listeners de scroll
                    addScrollListeners();
                    
                    // Inicia timer de mouse fora
                    if (!isMouseOverPopover) {
                        startMouseOutTimer();
                    }
                    
                    // Atualiza posição
                    $timeout(updatePosition, 10);
                } else {
                    console.log('🎯 Fechando popover');
                    clearAllTimers();
                    removeScrollListeners();
                    initialPopoverPosition = null; // Reset da posição inicial
                }
            });

            scope.$watch('width', function(newVal, oldVal) {
                if (newVal !== oldVal && scope.show) {
                    $timeout(updatePosition, 10);
                }
            });

            // EVENTOS GLOBAIS
            $document.on('click', handleClickOutside);
            $document.on('keydown', handleKeyDown);

            angular.element($window).on('resize', function() {
                if (scope.show) {
                    $timeout(updatePosition, 10);
                }
            });

            // CLEANUP
            scope.$on('$destroy', function() {
                
                clearAllTimers();
                removeScrollListeners();
                removeEditIcon();
                
                if (triggerElement) {
                    triggerElement.removeEventListener('change');
                }
                
                $document.off('click', handleClickOutside);
                $document.off('keydown', handleKeyDown);
                angular.element($window).off('resize');
            });
        }
    };
})

As partes adicionadas para possibilitar a seleção em um select deixei comentada para documentação e consulta futura

Actions #3

Updated by Henrique Novaes 6 months ago

  • Status changed from teste to concluído
Actions #4

Updated by jean sodré 6 months ago

  • Copied to Padrão #33: Checkbox diretiva hover e click added
Actions #5

Updated by jean sodré 6 months ago

  • Copied to Padrão #34: Ajustar diretiva de select para permitir desabilitar opções, dependendo da seleção do usuário added
Actions

Also available in: Atom PDF