반응형

메인 이미지

여러분들이 실무에 투입하면서 발생하는 문제 중 한가지를 알려 드리겠습니다 

 

다름 아니라 제가 겪은 이야기를 열거 하고 이야기 해볼텐대 한번쯤 이런 구조를 만나실거에요 

 

메인 페이지를 A    메인 페이지에서 표출시킨 팝업B    팝업 B에서 표출시킨 팝업C

 

총 3개의 페이지가 존재 하는 과정중에 C에서 어떠한 일련 작업을 위해 A에 있는 함수를 사용하고 A로 포커스가 가야하고 

A에서 요청한 작업이 완료되면 다시 C로 포커스가 이동 되어야 하는 이런 작업이였습니다 

사실 정확히는 이런 형태여야 합니다 

제일 밑에 A 그위에 B 그위에 C 이 상태로 작업이 끝나서 표출 되어야 하는 것입니다

 

그런데 지금 크롬에서는 자식창에서 부모창 focus()가 안됩니다

 

제가 이 문제때문에 한 2일정도를 focus() 함수에 관한 문서를 다 체크 해봤지만 결론은 크롬 정책으로 인해서 focus가 

동작하지 않는거였습니다 

이 함수를 악용하는 자식들이 있었다고 하더라구요 

 

불법을 저지르는 그런 사이트들이 사용자에게 클릭을 강제로 유도하게끔 하기위해 이 focus가 이용 됐다고 합니다 ㅎㅎ

그 나쁜놈들 입장에서는 이 버튼을 클릭 해야하는데 다른페이지로 이동 해버리면 의미가 없어지기 때문에 

버튼을 클릭해서 이 창을 닫기 라던지 그러한 버튼을 만들어 놓고 그 버튼을 누르지 않으면 페이지가 변경되지 

않도록 아마 계속 focus를 줬을겁니다 일반인 이라면 짜증나서라도 대충 눌러버리겠죠 성격 급한 (저 포함) 한국인들은

더더욱 그러지 않을까 조심스레 예측 해봅니다 ㅎㅎ 

 

그래서 지금 focus 함수가 동작하는 방식은 이렇습니다

 

부모에서 자식 부모에서 자식 무조건 이 구조로 동작합니다 제가 다른방법은 못찾았어요 있으면 알려주세요 저는 못찾았습니다 ㅎㅎ 

자 이모습에서 제일 위에 올라와있는 팝업창에서 어떠한 버튼이 있다고 가상으로 생각해봅시다 그러면 저 2개의 팝업이 

최소화 되고 지도 화면(메인페이지) 로 포커스가 이동되고 어떤 영역을 설정하고 나면 다시 위의 화면 처럼 복귀 되어야 합니다

 

근데 처음부터 문제가 있습니다 2개의 창을 뒤로 숨길 방법이 없습니다; 

이 이벤트의 시작은 제일 앞에 나와있는 팝업창이죠 ? 근데 그 팝업창에서 다른창들을 제어할수 없어요 제가 찾아본 바로는 그렇습니다 

 

물론 이런고민 하기 싫다면 모달 팝업이나 레이어 팝업을 쓰면 아무 문제가 없습니다

 

근데 이미 기구축 된 시스템을 내가 수정해야하고 이제 거지같은 IE가 사라지고 엣지와 크롬이 주된 브라우저 일텐데 

엣지와 크롬으로 넘어왔는데 focus가 안먹는다 하 .. 욕나오는 상황입니다 

 

그래서 제가 택한 방법은 C에서 버튼 클릭 시 opener를 이용해서 팝업 사이즈를 가장 작게 줄이고 제일 상단 좌측으로 옮

기는 겁니다 

 

그러기 위해서 사용된 함수는 window객체에 잇는 moveTo와 resizeTo 입니다 

 

근데 아셔야 하고 가장 중요한 부분이 제가 처음 말했던 권한 부분입니다 

어느 페이지가 opener 인지 그것이 중요합니다 

어찌됐건 두개의 팝업을 제어할 권한?이 있어야 합니다 

(이 부분은 제가 그냥 생각한  부분입니다 ㅎㅎ )

한개의 페이지에서 두개의 팝업의 권한을 가지고 있어야 한개의 페이지에서 두개의 팝업을 마음대로 

focus 할 수 있습니다 

그래서 저는 구조를 바꿨습니다 

 

팝업 view 구조

팝업을 표출 시키는 구조를 변경했습니다 두개의 팝업 다 하나의 페이지의 함수를 이용하도록 ㅎㅎ 

그렇게 되면 나머지 두개의 페이지의 오프너(opener)는 한개의 페이지가 됩니다 

즉 이제 두개 focus() 할 수 있는것이죠 ㅎㅎ 

사실 이렇게 구조를 바꾸기 싫었어요 ㅜ 제일 위로 올라와있는 팝업은 여기저기의 함수를 가져다가 쓰거든요 후 .. 

 

그래도 어쩔수 없는 것이기에 바꿨습니다 자 이제 구조는 됐고 

그럼 사이즈를 변경 해보겠습니다 

 

C에서 버튼 클릭 후 어떠한 함수 하나를 생성 해주고 그 함수에서 window 사이즈를 줄여줍니다 

줄여줄때 미리 사이즈를 저장 해놔야하겠죠 ?

B와 C둘다 저장해줍니다 객체로요 ㅎㅎ 소스가 길어지지만 C의 opener가 B가 아니라 A이기 때문에 ㅜㅜ 어쩔수 없어요 

  var winA = { "window" : windowA,
                    "width" : windowA.outerWidth,
                    "height" : windowA.outerHeight,
                    "left"   : windowA.outerLeft,
                    "right"  : windowA.outerRight 
              };
  var winB = { "window" : windowB,
                    "width" : windowB.outerWidth,
                    "height" : windowB.outerHeight,
                    "left"   : windowB.outerLeft,
                    "right"  : windowB.outerRight 
              };

각 페이지의 넓이 높이 왼쪽위치 오른족 위치 다 저장해줍니다 ㅎㅎ 

만약에 C의 opener가 A가 아니면 그냥 재귀 호출로 해도됩니다 근데 그게 안되죠 지금은.. 그래서 이렇게 진행합니다 ㅜㅜ

저렇게 저장해주고 배열에 푸시 해줍니다

 

var winArray = new Array();

winArray.push(winA);
winArray.push(winB);

자 그럼 함수 호출할 준비는 됐네요 그럼 함수를 짜봅시다 

 

function popupWindowHide (winArray){

    $.each(winArray, function(idx, item){

        try{

            setTimeout(function(){

                item.resizeTo(1,1);
                item.moveTo(0,0);

            }, 100);

        }catch(e){

            console.log(e);
        }

    });

}

 

이 함수로 팝업창의 사이즈를 줄여주도록 합시다 

 

그 이후에 메인 페이지에서 어떠한 작업을 실행시키고 콜백을 이용해서 원래 크기와 위치로 변경 해보도록 합시다 ㅎㅎ 

 

위의 함수를 이용해서 해도 되고 아니면 그냥 다른 함수를 사용해서 다시 원복 시켜도 됩니다 

 

B와 C의 사이즈와 위치를 저장 해놓은 이유가 이것입니다 ㅎㅎ 순서는 

B를 먼저 focus하고 그 이후에 C를 focus합니다

 

오늘 알아본 내용을 요점정리 해보자면 

 

1. window.focus()는 부모에서 자식은 가능하나 자식에서 부모는 불가능 하다 

2. 팝업이 2개 이상인데 순서대로 focus를 주어 맨 앞으로 띄우고 싶다면 구조를 mainPage에서 호출하게 변경하자 

3. 각 팝업의 사이즈를 미리 변수에 저장한 다음 축소 시키고 원하는 동작이 끝나면 다시 원상복귀 시키자 

 

이렇게 정리가 됩니다 

 

제가 너무 고생해서 그렇지 생각보다 간단하고 조금만 더 생각해보면 훨씬 더 좋은 코드가 있을거라 생각합니다 ㅎㅎ 

기존에는 A 자식  B 자식 C 이런 형태였어서 너무 고생하는 바람에 다른분들도 이런 경우가 있지 않을까 

하는 생각에 작성합니다 감사합니다

 

반응형

'Developer > Javascript' 카테고리의 다른 글

[javascript]radio 전체 체크하기  (0) 2022.07.12
[javascript]JSON  (0) 2022.07.07
[javascript]생성자(constructor)  (0) 2022.06.22
[javascript]Document  (0) 2022.06.21
[javascript] 날짜를 표현하는 Date 객체  (0) 2022.06.16
복사했습니다!