<jsp:include>で他のjspファイルの要素を取り込んだ後、window.onloadしようとした時にハマった。
のでメモ。
<html>
<head>
<script defer src="/path/to/jquery/jquery-3.2.1.min.js"></script>
<script src="/js/hougei.js"></script>
</head>
<body>
<jsp:include page="/jsp/hooogeee.jsp"></jsp:include>
</body>
</html>
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page import="java.util.concurrent.TimeUnit" %>
<%!
private void outHello(HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
out.println("<div class=\"hello\" style=\"display:none;\">");
out.println("Hello World.");
out.println("</div>");
out.close();
}
%>
<%
TimeUnit.SECONDS.sleep(1000);
outHello(response);
%>
$(window).on('load', function () { //全ての読み込みが完了したら実行
$('.hello').css('display', 'block');
});
意図している動作は jsp:includeが終わったタイミングでwindow.onloadイベントが発火され、hougei.jsによってdisplayプロパティが書き換わり"Hello World."が表示されることだが、この場合、なにも表示されない。
試しに console.log($('.hello').length) をしてみても 0 が返される。
原因はjsp:includeの仕組みにあった。
jsp:includeの仕組み
このタグは、指定されたファイルをJSPの一部としてインクルードするのではなく、指定されたURLにリクエストを送信し、その応答内容を動的にリクエスト元に挿入して表示します。インクルードされるページとインクルードを行うJSPとは独立したページとして存在するため、インクルードされたファイルが更新されれば、元のJSP自体が更新されていなくても、動的に更新内容が結果に反映されます。
なるほど、<jsp:include> の処理を理解し間違えていたようだ。他jspをコードごと挿入、表示するのではなく、リクエストした結果をレスポンスとして挿入しているため、window.onloadイベントはあくまでhoge.jspが読み込まれたタイミングで発火してしまう。
今回意図した通りに処理を行うためには
<jsp:include page="/jsp/hooogeee.jsp"></jsp:include>
ではなく、
<%@ include file="/jsp/hooogeee"%>
を使えばよかった。
ただし、コードをそのまま挿入しているのでinclude先での多重宣言やimportに注意する。