Decoupling HTML and JavaScript
Using the DOM model to specify event handlers reduces the degree of coupling between HTML and JavaScript.
Adding the id attribute to an element makes it easier to specify an event handler:
<input type="button" id="some-button" value="Button" />
window.onload = function() { var btn = document.getElementById("some-button"); btn.onclick = function() { //TODO }; };
The onload event occurs when all elements of the document (including images) are ready. There is also a disadvantage to specifying event handlers using the window's onload event.
- You may need to add global attributes (id, class, title) that you didn't need until now.
- Many images in the document may slow down the handler registration. (You can use JQuery to improve this)
This section describes how to remove the handler specified in the HTML attribute and use DOM to specify handlers. We will practice with the view.jsp of the bulletin board.
Attachment link and Attachment delete link
Modify the download link and the delete link as follows.
<div id="detail"> <div id="date-writer-hit"> edited <fmt:formatDate pattern="yyyy.MM.dd HH:mm:ss" value="${regdate }" /> by ${name } hit {hit } </div> <div id="article-content">${content }</div> <div id="file-list" style="text-align: right;"> <c:forEach var="file" items="${attachFileList }" varStatus="status"> <div class="attach-file"> <a href="#" title="${file.filename }" class="download">${file.filename }</a> <security:authorize access="#email == principal.username or hasRole('ROLE_ADMIN')"> <a href="#" title="${file.attachFileNo }">Del</a> </security:authorize> </div> </c:forEach> </div> </div>
Add the following between <script> and </script>.
window.onload = initPage; function initPage() { //Download link and the delete link var file_list = document.getElementById("file-list"); var fileLinks = file_list.getElementsByTagName("a"); for (var i = 0; i < fileLinks.length; i++) { var fileLink = fileLinks[i]; if (fileLink.className == "download") { fileLink.onclick = function() { var attachFileNo = this.title; var form = document.getElementById("downForm"); form.attachFileNo.value = attachFileNo; form.submit(); return false; }; } else { fileLink.onclick = function() { var attachFileNo = this.title; var chk = confirm("Are you sure you want to delete it?"); if (chk === true) { var form = document.getElementById("deleteAttachFileForm"); form.attachFileNo.value = attachFileNo; form.submit(); return false; } }; } } //TODO: Add code here }//initPage function end
Comment
Modify as follows.
<div id="all-comments"> <c:forEach var="comment" items="${commentList }" varStatus="status"> <div class="comments"> <span class="writer">${comment.name }</span> <span class="date">${comment.regdate }</span> <security:authorize access="#comment.email == principal.username or hasRole('ROLE_ADMIN')"> <span class="modify-del"> <a href="#">Modify</a> | <a href="#" title="${comment.commentNo }">Del</a> </span> </security:authorize> <div class="comment-memo">${comment.memo }</div> <form class="comment-form" action="updateComment" method="post" style="display: none"> <input type="hidden" name="commentNo" value="${comment.commentNo }" /> <input type="hidden" name="boardCd" value="${param.boardCd }" /> <input type="hidden" name="articleNo" value="${param.articleNo }" /> <input type="hidden" name="page" value="${param.page }" /> <input type="hidden" name="searchWord" value="${param.searchWord }" /> <div style="text-align: right;"> <a href="#">Submit</a> | <a href="#">Cancel</a> </div> <div> <textarea class="comment-textarea" name="memo" rows="7" cols="50">${comment.memo }</textarea> </div> </form> </div> </c:forEach> </div>
Add the following outside the initPage() function:
function commentUpdate(e) { var me = getActivatedObject(e); var form = me.parentNode; while (form.className != "comment-form") { form = form.parentNode; } form.submit(); return false; } function modifyCommentToggle(e) { var me = getActivatedObject(e); var comments = me.parentNode; while (comments.className != "comments") { comments = comments.parentNode; } var div = comments.getElementsByTagName("div")[0];//Comment p var form = comments.getElementsByTagName("form")[0];//Comment form if (div.style.display) { div.style.display = ''; form.style.display = 'none'; } else { div.style.display = 'none'; form.style.display = ''; } return false; } /* Head First Ajax */ function getActivatedObject(e) { var obj; if (!e) { //IE Old version obj = window.event.srcElement; } else if (e.srcElement) { //IE 7 obj = e.srcElement; } else { //DOM Level 2 obj = e.target; } return obj; }
Add the following to initPage().
var allComments = document.getElementById("all-comments"); var divs = allComments.getElementsByTagName("div"); for (i = 0; i < divs.length; i++) { if (divs[i].className == "comments") { var comments = divs[i]; var spans = comments.getElementsByTagName("span"); for (var j = 0; j < spans.length; j++) { if (spans[j].className === "modify-del") { var md = spans[j]; var commentModifyLink = md.getElementsByTagName("a")[0];//Modify link commentModifyLink.onclick = modifyCommentToggle; var commentDelLink = md.getElementsByTagName("a")[1];//Delete link commentDelLink.onclick = function() { var commentNo = this.title; var chk = confirm("Are you sure you want to delete it?"); if (chk === true) { var form = document.getElementById("deleteCommentForm"); form.commentNo.value = commentNo; form.submit(); return false; } }; } //Modify link in form var form = comments.getElementsByTagName("form")[0]; var div = form.getElementsByTagName("div")[0]; commentModifyLink = div.getElementsByTagName("a")[0]; commentModifyLink.onclick = commentUpdate; //Cancel link in form var cancelLink = div.getElementsByTagName("a")[1]; cancelLink.onclick = modifyCommentToggle; } } }
Next article link and Prev article link
Modify as follows.
<div id="next-prev"> <c:if test="${nextArticle != null }"> <p>Next Article : <a href="#" title="${nextArticle.articleNo }">${nextArticle.title } </a></p> </c:if> <c:if test="${prevArticle != null }"> <p>Prev Article : <a href="#" title="${prevArticle.articleNo }">${prevArticle.article.title }</a></p> </c:if> </div>
Add the following to initPage().
//Next Article link, Prev Article link var nextPrev = document.getElementById("next-prev"); links = nextPrev.getElementsByTagName("a"); for (i = 0; i < links.length; i++) { links[i].onclick = function() { var form = document.getElementById("viewForm"); form.articleNo.value = this.title; form.submit(); return false; }; }
Modify/Del/Next Article/Prev Article/List/New Article Button
There are two view-menu classes surrounding buttons, so we need to modify both.
<div class="view-menu" ..> <security:authorize access="#email == principal.username or hasRole('ROLE_ADMIN')"> <div class="fl"> <input type="button" value="Modify" class="goModify" /> <input type="button" value="Del" class="goDelete" /> </div> </security:authorize> <div class="fr"> <c:if test="${nextArticle != null }"> <input type="button" value="Next Article" title="${nextArticle.articleNo }" class="next-article" /> </c:if> <c:if test="${prevArticle != null }"> <input type="button" value="Prev Article" title="${prevArticle.articleNo }" class="prev-article" /> </c:if> <input type="button" value="List" class="goList" /> <input type="button" value="New Article" class="goWrite" /> </div> </div>
Add the following to initPage().
//Modify Button var modifyBtns = document.getElementsByClassName("goModify"); i = modifyBtns.length; while (i--) { modifyBtns[i].onclick = function() { var form = document.getElementById("modifyForm"); form.submit(); }; } //Del Button var deleteBtns = document.getElementsByClassName("goDelete"); i = deleteBtns.length; while (i--) { deleteBtns[i].onclick = function() { var chk = confirm('Are you sure you want to delete it?'); if (chk === true) { var form = document.getElementById("delForm"); form.submit(); } }; } //Next Article Button var nextArticleBtns = document.getElementsByClassName("next-article"); i = nextArticleBtns.length; while (i--) { nextArticleBtns[i].onclick = function() { var form = document.getElementById("viewForm"); form.articleNo.value = this.title; form.submit(); }; } //Prev Article Button var prevArticleBtns = document.getElementsByClassName("prev-article"); i = prevArticleBtns.length; while (i--) { prevArticleBtns[i].onclick = function() { var form = document.getElementById("viewForm"); form.articleNo.value = this.title; form.submit(); }; } //List Button var listBtns = document.getElementsByClassName("goList"); i = listBtns.length while (i--) { listBtns[i].onclick = function() { var form = document.getElementById("listForm"); form.submit(); }; } //New Article Button var writeBtns = document.getElementById("goWrite"); i = writeBtns.length; while(i--) { writeBtns[i].onclick = function() { var form = document.getElementById("writeForm"); form.submit(); }; }
Title link, Page move link, New Article Button
Modify as follows.
<table id="list-table" class="bbs-table"> <tr> <th style="width: 60px">NO</th> <th>TITLE</th> <th style="width: 84px;">DATE</th> <th style="width: 60px;">HIT</th> </tr> <!-- List items start --> <c:forEach var="article" items="${list }" varStatus="status"> <tr> <td style="text-align: center;"> <c:choose> <c:when test="${param.articleNo == article.articleNo }"> <img src="/resources/images/arrow.gif" alt="You are reading this" /> </c:when> <c:otherwise> ${listItemNo - status.index } </c:otherwise> </c:choose> </td> <td> <a href="#" title="${article.articleNo }">${article.title }</a> <c:if test="${article.attachFileNum > 0 }"> <img src="/resources/images/attach.png" alt="Attach File" style="vertical-align: middle;" /> </c:if> <c:if test="${article.commentNum > 0 }"> <span class="bbs-strong">[${article.commentNum }]</span> </c:if> </td> <td style="text-align: center;"> <fmt:formatDate pattern="yyyy.MM.dd" value="${article.regdate }" /> </td> <td style="text-align: center;">${article.hit }</td> </tr> </c:forEach> <!-- List items end --> </table> <div id="paging"> <c:if test="${prevPage > 0 }"> <a href="#" title="${prevPage }">[Prev]</a> </c:if> <c:forEach var="i" begin="${firstPage }" end="${lastPage }"> <c:choose> <c:when test="${param.page == i }"> <span class="bbs-strong">${i }</span> </c:when> <c:otherwise> <a href="#" title="${i }">${i }</a> </c:otherwise> </c:choose> </c:forEach> <c:if test="${nextPage > 0 }"> <a href="#" title="${nextPage }">[Next]</a> </c:if> </div> <div id="list-menu"> <input type="button" value="New" /> </div>
Add the following to initPage().
//Title links in detail view var listTable = document.getElementById("list-table"); links = listTable.getElementsByTagName("a"); for (i = 0; i < links.length; i++) { links[i].onclick = function() { var form = document.getElementById("viewForm"); form.articleNo.value = this.title; form.submit(); return false; }; } //Paging var paging = document.getElementById("paging"); links = paging.getElementsByTagName("a"); for (i = 0; i < links.length; i++) { links[i].onclick = function() { var form = document.getElementById("listForm"); form.page.value = this.title; form.submit(); return false; }; } //New Article button var listMenu = document.getElementById("list-menu"); writeBtn = listMenu.getElementsByTagName("input")[0]; writeBtn.onclick = function() { var form = document.getElementById("writeForm"); form.submit(); };
Attachment link and Attachment delete link (jQuery)
Let's change the JavaScript DOM example to use jQuery.
Download the latest version of jQuery from https://jquery.com/ and put the jQuery file in the /js folder. Add the following between <head> and </head> of view.jsp.
<script src="/resources/js/jquery-3.3.1.min.js"></script>
The HTML code has nothing to change.
<div id="detail"> <div id="date-writer-hit"> edited <fmt:formatDate pattern="yyyy.MM.dd HH:mm:ss" value="${regdate }" /> by ${name } hit {hit } </div> <div id="article-content">${content }</div> <div id="file-list" style="text-align: right;"> <c:forEach var="file" items="${attachFileList }" varStatus="status"> <div class="attach-file"> <a href="#" title="${file.filename }" class="download">${file.filename }</a> <security:authorize access="#email == principal.username or hasRole('ROLE_ADMIN')"> <a href="#" title="${file.attachFileNo }">Del</a> </security:authorize> </div> </c:forEach> </div> </div>
Comment out all the existing contents of the JavaScript, add the following code.
$(document).ready(function() { $('#file-list a.download').click(function(e) { e.preventDefault(); var filename = this.title; $('#downForm input[name*=filename]').val(filename); $('#downForm').submit(); }); $('#file-list a:not(.download)').click(function(e) { e.preventDefault(); var chk = confirm("Are you sure you want to delete it?"); if (chk === true) { var attachFileNo = this.title; $('#deleteAttachFileForm input[name*=attachFileNo]').val(attachFileNo); $('#deleteAttachFileForm').submit(); } }); });
Comment(jQuery)
Modify as follows.
<div id="all-comments"> <c:forEach var="comment" items="${commentList }"> <div class="comments"> <span class="writer">${comment.username }</span> <span class="date">${comment.regdate }</span> <c:if test="${user.username == comment.username }" > <span class="modify-del"> <a href="#" class="comment-modify-link">Modify</a> | <a href="#" class="comment-delete-link" title="${comment.commentNo }">Del</a> </span> </c:if> <div class="comment-memo">${comment.memo }</div> <form class="comment-form" action="updateComment" method="post" style="display: none"> <input type="hidden" name="commentNo" value="${comment.commentNo }" /> <input type="hidden" name="boardCd" value="${param.boardCd }" /> <input type="hidden" name="articleNo" value="${param.articleNo }" /> <input type="hidden" name="page" value="${param.page }" /> <input type="hidden" name="searchWord" value="${param.searchWord }" /> <div style="text-align: right;"> <a href="#" class="comment-modify-submit-link">Submit</a> | <a href="#" class="comment-modify-cancel-link">Cancel</a> </div> <div> <textarea class="comment-textarea" name="memo" rows="7" cols="50">${comment.memo }</textarea> </div> </form> </div> </c:forEach> </div>
Add the following to $(document).ready(function() {} function.
//Comments $('.comments').click(function(e) { e.preventDefault(); if ($(e.target).is('.comment-modify-link')) { var $form = $(e.target).parent().parent().find('.comment-form'); var $div = $(e.target).parent().parent().find('.comment-memo'); if ($form.is(':hidden') === true) { $form.show(); $div.hide(); } else { $form.hide(); $div.show(); } } else if ($(e.target).is('.comment-modify-cancel-link')) { var $form = $(e.target).parent().parent().parent().find('.comment-form'); var $div = $(e.target).parent().parent().parent().find('.comment-memo'); if ($form.is(':hidden') === true) { $form.show(); $div.hide(); } else { $form.hide(); $div.show(); } } else if ($(e.target).is('.comment-modify-submit-link')) { var $form = $(e.target).parent().parent().parent().find('.comment-form'); $form.submit(); } else if ($(e.target).is('.comment-delete-link')) { var chk = confirm('Are you sure you want to delete it?'); if (chk === false) { return; } var $commentNo = $(e.target).attr('title'); $('#deleteCommentForm input[name*=commentNo]').val($commentNo); $('#deleteCommentForm').submit(); } });
Prev Article link and Next Article link (jQuery)
The HTML code has nothing to change.
<div id="next-prev"> <c:if test="${nextArticle != null }"> <p>Next Article : <a href="#" title="${nextArticle.articleNo }">${nextArticle.title }</a></p> </c:if> <c:if test="${prevArticle != null }"> <p>Prev Article : <a href="#" title="${prevArticle.articleNo }">${prevArticle.title }</a></p> </c:if> </div>
Add the following to $(document).ready(function() {} function.
$('#next-prev a').click(function(e) { e.preventDefault(); var articleNo = this.title; $('#viewForm input[name*=articleNo]').val(articleNo); $('#viewForm').submit(); });
Modify/Del/Next Article/Prev Article/List/New Article Button (jQuery)
The HTML code has nothing to change.
<div class="view-menu" .. > <security:authorize access="#email == principal.username or hasRole('ROLE_ADMIN')"> <div class="fl"> <input type="button" value="Modify" class="goModify" /> <input type="button" value="Del" class="goDelete" /> </div> </security:authorize> <div class="fr"> <c:if test="${nextArticle != null }"> <input type="button" value="Next Article" title="${nextArticle.articleNo }" class="next-article" /> </c:if> <c:if test="${prevArticle != null }"> <input type="button" value="Prev Article" title="${prevArticle.articleNo }" class="prev-article" /> </c:if> <input type="button" value="List" class="goList" /> <input type="button" value="New Article" class="goWrite" /> </div> </div>
Add the following to $(document).ready(function() {} function.
//Modify Button $('.goModify').click(function() { $('#modifyForm').submit(); }); //Del Button $('.goDelete').click(function() { var chk = confirm('Are you sure you want to delete it?'); if (chk === true) { $('#delForm').submit(); } }); //Next Article Button $('.next-article').click(function() { var articleNo = this.title; $('#viewForm input[name*articleNo]').val(articleNo); $('#viewForm').submit(); }); //Prev Article Button $('.prev-article').click(function() { var articleNo = this.title; $('#viewForm input[name*articleNo]').val(articleNo); $('#viewForm').submit(); }); //List Button $('.goList').click(function() { $('#listForm').submit(); }); //New Article Button $('.goWrite').click(function() { $('#writeForm').submit(); });
Title link, Page move links, New Article Button (jQuery)
The relevant code is the same as before.
<table id="list-table" class="bbs-table"> <tr> <th style="width: 60px">NO</th> <th>TITLE</th> <th style="width: 84px;">DATE</th> <th style="width: 60px;">HIT</th> </tr> <!-- List items start --> <c:forEach var="article" items="${list }" varStatus="status"> <tr> <td style="text-align: center;"> <c:choose> <c:when test="${param.articleNo == article.articleNo }"> <img src="/resources/images/arrow.gif" alt="You are reading this" /> </c:when> <c:otherwise> ${listItemNo - status.index } </c:otherwise> </c:choose> </td> <td> <a href="#" title="${article.articleNo }">${article.title }</a> <c:if test="${article.attachFileNum > 0 }"> <img src="/resources/images/attach.png" alt="Attach File" style="vertical-align: middle;" /> </c:if> <c:if test="${article.commentNum > 0 }"> <span class="bbs-strong">[${article.commentNum }]</span> </c:if> </td> <td style="text-align: center;"> <fmt:formatDate pattern="yyyy.MM.dd" value="${article.regdate }" /> </td> <td style="text-align: center;">${article.hit }</td> </tr> </c:forEach> <!-- List items end --> </table> <div id="paging"> <c:if test="${prevPage > 0 }"> <a href="#" title="${prevPage }">[Prev]</a> </c:if> <c:forEach var="i" begin="${firstPage }" end="${lastPage }"> <c:choose> <c:when test="${param.page == i }"> <span class="bbs-strong">${i }</span> </c:when> <c:otherwise> <a href="#" title="${i }">${i }</a> </c:otherwise> </c:choose> </c:forEach> <c:if test="${nextPage > 0 }"> <a href="#" title="${nextPage }">[Next]</a> </c:if> </div> <div id="list-menu"> <input type="button" value="New Article" /> </div>
Add the following to $(document).ready(function() {} function.
//Title links in Detailed view $('#list-table a').click(function(e) { e.preventDefault(); var articleNo = this.title; $('#viewForm input[name*articleNo]').val(articleNo); $('#viewForm').submit(); }); //Paging $('#paging a').click(function(e) { e.preventDefault(); var page = this.title; $('#listForm input[name*=page]').val(page); $('#listForm').submit(); }); //New Article Button $('#list-menu input').click(function() { $('#writeForm').submit(); });
It is up to you to use pure JavaScript or jQuery.