From 5106b3f4e51ea7170c460c18478519f2c77df643 Mon Sep 17 00:00:00 2001 From: syc0123 Date: Thu, 26 Mar 2026 15:00:54 +0900 Subject: [PATCH] =?UTF-8?q?[RAPID-fix]=20Select2=20=EB=93=9C=EB=9E=98?= =?UTF-8?q?=EA=B7=B8=20=EB=B3=B5=EC=82=AC:=20capturing=20phase=EB=A1=9C=20?= =?UTF-8?q?mouseTarget=20=EC=84=A0=EC=A0=90=ED=95=98=EC=97=AC=20=EC=97=B4?= =?UTF-8?q?=EB=A6=BC=20=EC=99=84=EC=A0=84=20=EC=B0=A8=EB=8B=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - capturing phase에서 mouseTarget 플래그를 Select2 핸들러보다 먼저 설정 - Select2의 mousedown → select2:opening 시점에 이미 차단 플래그가 활성화됨 - 드롭다운 열리기 전에 텍스트 드래그 가능 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../estimateAndOrderRegistFormPopup.jsp | 40 +++++++++++-------- .../contractMgmt/estimateRegistFormPopup.jsp | 40 +++++++++++-------- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/WebContent/WEB-INF/view/contractMgmt/estimateAndOrderRegistFormPopup.jsp b/WebContent/WEB-INF/view/contractMgmt/estimateAndOrderRegistFormPopup.jsp index 51cbaab..4b48164 100644 --- a/WebContent/WEB-INF/view/contractMgmt/estimateAndOrderRegistFormPopup.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/estimateAndOrderRegistFormPopup.jsp @@ -151,41 +151,49 @@ // ===== Select2 드래그 복사 지원 ===== function fn_initSelect2DragCopy() { - var mouseTarget = null; // 마우스 조작 중인 select 요소 + var mouseTarget = null; + var wasDragged = false; + var startX = 0, startY = 0; - // select2:opening을 상시 감시 — 마우스 조작 중이면 열림 차단 + // select2:opening 상시 감시 — mouseTarget이 설정되어 있으면 열림 차단 $(document).on('select2:opening', '#itemListTable select', function(e) { if(mouseTarget === this) { e.preventDefault(); } }); - // mousedown: 이벤트 전파는 그대로 (네이티브 텍스트 선택 유지) - $(document).on('mousedown', '#itemListTable .select2-selection', function(e) { + // capturing phase: Select2 핸들러보다 먼저 mouseTarget 플래그 설정 + document.addEventListener('mousedown', function(e) { + var $sel = $(e.target).closest('#itemListTable .select2-selection'); + if($sel.length === 0) return; if($(e.target).hasClass('select2-selection__clear')) return; - var $container = $(this).closest('.select2-container'); + var $container = $sel.closest('.select2-container'); var $select = $container.prev('select'); - mouseTarget = $select[0]; // 열림 차단 활성화 + mouseTarget = $select[0]; // Select2 열림 차단 활성화 + wasDragged = false; + startX = e.pageX; + startY = e.pageY; - var startX = e.pageX, startY = e.pageY; - var wasDragged = false; - - $(document).on('mousemove.s2drag', function(ev) { + var onMove = function(ev) { if(Math.abs(ev.pageX - startX) > 3 || Math.abs(ev.pageY - startY) > 3) { wasDragged = true; } - }); + }; - $(document).on('mouseup.s2drag', function() { - $(document).off('mousemove.s2drag mouseup.s2drag'); + var onUp = function() { + document.removeEventListener('mousemove', onMove); + document.removeEventListener('mouseup', onUp); if(!wasDragged) { - mouseTarget = null; // 차단 해제 + mouseTarget = null; $select.select2('open'); } setTimeout(function() { mouseTarget = null; }, 50); - }); - }); + }; + + document.addEventListener('mousemove', onMove); + document.addEventListener('mouseup', onUp); + }, true); // capturing phase — Select2보다 먼저 실행 } $(function() { diff --git a/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp b/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp index ac3d322..6247ea5 100644 --- a/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp @@ -152,41 +152,49 @@ // ===== Select2 드래그 복사 지원 ===== function fn_initSelect2DragCopy() { - var mouseTarget = null; // 마우스 조작 중인 select 요소 + var mouseTarget = null; + var wasDragged = false; + var startX = 0, startY = 0; - // select2:opening을 상시 감시 — 마우스 조작 중이면 열림 차단 + // select2:opening 상시 감시 — mouseTarget이 설정되어 있으면 열림 차단 $(document).on('select2:opening', '#itemListTable select', function(e) { if(mouseTarget === this) { e.preventDefault(); } }); - // mousedown: 이벤트 전파는 그대로 (네이티브 텍스트 선택 유지) - $(document).on('mousedown', '#itemListTable .select2-selection', function(e) { + // capturing phase: Select2 핸들러보다 먼저 mouseTarget 플래그 설정 + document.addEventListener('mousedown', function(e) { + var $sel = $(e.target).closest('#itemListTable .select2-selection'); + if($sel.length === 0) return; if($(e.target).hasClass('select2-selection__clear')) return; - var $container = $(this).closest('.select2-container'); + var $container = $sel.closest('.select2-container'); var $select = $container.prev('select'); - mouseTarget = $select[0]; // 열림 차단 활성화 + mouseTarget = $select[0]; // Select2 열림 차단 활성화 + wasDragged = false; + startX = e.pageX; + startY = e.pageY; - var startX = e.pageX, startY = e.pageY; - var wasDragged = false; - - $(document).on('mousemove.s2drag', function(ev) { + var onMove = function(ev) { if(Math.abs(ev.pageX - startX) > 3 || Math.abs(ev.pageY - startY) > 3) { wasDragged = true; } - }); + }; - $(document).on('mouseup.s2drag', function() { - $(document).off('mousemove.s2drag mouseup.s2drag'); + var onUp = function() { + document.removeEventListener('mousemove', onMove); + document.removeEventListener('mouseup', onUp); if(!wasDragged) { - mouseTarget = null; // 차단 해제 + mouseTarget = null; $select.select2('open'); } setTimeout(function() { mouseTarget = null; }, 50); - }); - }); + }; + + document.addEventListener('mousemove', onMove); + document.addEventListener('mouseup', onUp); + }, true); // capturing phase — Select2보다 먼저 실행 } $(function() {