Javascript

[오류]

 - IE 특정 버전에서 iframe 재호출 시 input text 박스 미작동

 - iframe 삭제 후 widnow events를 잃어버리는 현상

 - IE9버전부터 존재하는 오류.

  (같은 IE 11버전이라도 하위 버전에 따라 해당 오류 발생 유무 달랐음)

 

[해결과정]

  구글링해서 확인 해보니 iframe load시 첫번째 input 박스에 focus 주는 방식이 있었음.

  하지만 나의 경우 첫번째 input box에 focus 이벤트 로직이 존재하였고, 모든 layer 팝업에 이를 세팅해주는 방법은

  좋지 못한 방법이었음.

 

  IE환경 세팅으로 최대한 문제를 해결해보려 했으나 해결되지 않았고,

  결국 layer 팝업을 호출하는 공통함수에 아래와 같이 iframe 자체에 focus를 주어서 해결

  iframe[0].contentWindow.focus();

 

 

[참고사이트]

https://stackoverflow.com/questions/49372845/on-ie11-cannot-type-in-input-box-after-removing-iframe-with-contenteditable-tru

https://skypotato-note.tistory.com/121

 

 

jsp에서 jqery template을 사용할 때 생기는 문제 및 해결방안


※ 문제

jsp의 EL Tag도 ${} 를 쓰고

jquery의 template도 ${} 를 쓰기 때문에

jqery의 template을 사용하고자 ${}를 쓰게 되면

서버단의 jsp에서 EL Tag로 인식하여 오류가 발생한다.


※ 해결책 


1) 해당 페이지에 ELignored 명시

<%@page isELIgnored="true" %>

2) web.xml Config 설정


    true

3) 코드 기입 방법(변수)

3-1) {{html item}}

3-2) {{= item}}

{{html rec2.LINE_NO }}
{{= rec2.LINE_NO }}



4) 코드 기입 방법(함수)

- template에서 함수 사용시 ${}는 필수이기 때문에 jsp의 EL Tag와 겹치지 않는 것이 중요하다.

4-1) ${} 안에 ${ '${' } 로 명시해주기

4-2) ${} 앞에 \ 사용

${'${'} formatter.number(( rec2.AM_DR ) }
\${ formatter.number(( rec2.AM_DR ) }









1. event 선언부

 

$(document).on("change","#PAY_TYPE",function (event,first_load) {     if(first_load){         // true logic     }     else{         // false logic     } });


2. event 호출부

$("#PAY_TYPE").trigger("change",[true]);


http://www.abc.com 이하 "abc"에서 http://www.xyz.com 이하 "xyz"을 window.open(); 형태로 팝업을 호출한 후

xyz(자식)에서 abc(부모)의 함수를 호출 하거나 파라미터에 접근하려고 할 경우


크로스도메인 보안 이슈로 opener로 접근을 하지 못한다. (팝업 호출 시 도메인주소가 달라져서 opener객체를 잃어버림)


오류로그 : Uncaught DOMException: Blocked a frame with origin "http://www.xyz.com" from accessing a cross-origin frame.


이 때 해결방법이 2가지가 있다.



1. postMessage를 사용할 수 있다.(이 경우 IE 8 부터 지원된다)


2. iframe을 사용하여 abc(부모)아래에 xyz(자식)의 jsp호출 후 호출한 iframe영역에서 팝업창을 띄우면 된다. (팝업 창에서는 opener.parent.으로 접근하면 된다)


예제 소스 정리는 나중에 해서 업로드 하자.......! 지금은 바쁘다!

* 현재 pdf다운로드 요건 : 

1. html to pdf 다운로드 기능

2. 다건의 데이터 클릭 후 다운로드 버튼 누를 경우 다건의 html 페이지를 하나의 pdf파일로 다운로드

-> 서버단에서 html 페이지를 읽어와 하나의 pdf파일로 합치기 때문에 로딩시간이 길다.


* 이슈사항 : 

URL 경로를 통해 파일을 다운로드 받는 것이 아닌, 빽단에서 response의 header를 아래와 같이 BufferOutputStream으로 출력할 경우

파일 다운로드 완료 타이밍을 어떻게 확인할 수 있나?

if (request.getHeader("User-Agent").toLowerCase().indexOf("msie") > -1 ||
        request.getHeader("User-Agent").toLowerCase().indexOf("edge") > -1 ||
        request.getHeader("User-Agent").toLowerCase().indexOf("rv:11.0") > -1
        ) {
    response.setHeader("Content-Disposition", "attachment; filename=\"" +
                                   (URLEncoder.encode(downloadPdfFilename,"UTF-8").replaceAll("\\+","%20")) + "\"");
} else {
    response.setHeader("Content-Disposition", "attachment; filename=\"" +
                                   (new String(downloadPdfFilename.getBytes("UTF-8"), "8859_1")) + "\"");
}
//out.clear();
//out = pageContext.pushBody();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream os = new BufferedOutputStream(response.getOutputStream());
int read = 0;
while ((read = in.read()) != -1) {
    os.write(read);
}
// response.flushBuffer();
in.close();
// os.flush();
os.close();
file.delete();

* 시도해본 방법


1. response.getWriter().print() 메서드를 통해 script로 로딩바 종료 메서드 호출.

StringBuffer script = new StringBuffer();
script.append("<script type="\"text/javascript\"">");
script.append("tmsComm.destroyProgressBar();");
script.append("</script>");
response.getWriter().print(script.toString());

-> response를 통해 buffer stream으로 파일도 출력하고, text로도 출력해 script단을 호출하려 했으나

    다음과 같은 에러 발생(java.lang.IllegralStateException)



구글링 결과 response는 2가지 형식으로 출력이 불가능하다. 이미 stream형태로 출력하기 때문에 text로 출력 불가

(상식적으로도 그러는게 당연)


2. jsp단에서 직접 <script>코드 추가



20row의 sout은 back단의 시스템 로그에 찍히지만, 

23row의 alert는 response로 이미 파일 스트림을 출력했으므로 front단은 읽지 않아서 alert이 찍히지 않는다.

따라서 이 방법으로도 구별 불가.


3. form의 target을 iframe으로 주어서 iframe onload(파일다운로드 작업 완료) 이벤트 시 호출

// 1번 방법
$(document).on("load","#hideIframe",function (){
        alert("aaaa");
        tmsComm.destroyProgressBar();
});
// 2번 방법
$("#hideIframe").on("load",function () {
        alert("aaaa");
        tmsComm.destroyProgressBar();
});
// 3번 방법
 document.getElementById("hideIframe").onload = function () {
        alert("ccccccc");
};

-> 1~3번 방법까지 다 시도 해봤으나 onload 이벤트 메소드 자체가 호출 되지가 않는다.

-> 구글링 결과 stackoverflow형님에게서 다음과 같은 결과를 얻을 수 있었다.


         Unfortunately it is not possible to use an iframe's onload event in Chrome if the content is an attachment.


         안타깝게도 콘텐츠가 첨부 파일 인 경우 Chrome에서 iframe onload 이벤트를 사용할 수 없습니다.


4. ajax 호출(?) ->  ajax의 경우 string/xml통신 기반이다. 따라서 response값을 string값으로 url주소를 넘겨주어서 파일 다운로드가 가능하지만

 언제 다운로드가 완료됬는지는 확인 불가. 게다가 지금 상황은 response값을 파일 스트림으로 곧바로 넘겨주는 경우이다.




* 해결책


약 4~5시간의 뻘짓 끝에 stackoverflow형님의 도움을 받아 해결. 


형님 왈 : I hate this, but I couldn't find any other way than checking whether it is still loading or not except by checking at intervals.


나도 이 방법이 싫지만 아직 로딩 중인지 아닌지를 확인하는 방법을 이 방법 외에는 어떤 방법도 찾지 못했다.

var timer = setInterval(function () {
    iframe = document.getElementById('iframedownload');
    var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
    // Check if loading is complete
    if (iframeDoc.readyState == 'complete' || iframeDoc.readyState == 'interactive') {
        tmsComm.destroyProgressBar();
        clearInterval(timer);
        return;
    }
}, 4000); 

이 방법은 파일 다운로드 시에 4초에 1번씩 iframe의 상태값을 확인해서 iframe상태가 complete이거나 interactive인 경우 timer와 로딩바를 중단시키는 방법이다.


결국 찾다찾다 이 방법을 채택하였지만 완벽하지 못하다. 가장 좋은 방법은 이 것일 거 같다.


※ response를 파일 스트림으로 넘기는 것이 아니라 URL로 던져주어서 서버의 파일을 다운로드 받게 하고 서버단에서는 특정날짜/특정시간에 PDF파일들을 삭제하는 쉘 스크립트를 작성하는 것


이 부분은 고도화 작업시에 다시 진행할 예정이다.

+ Recent posts