728x90
반응형
jQuery Ajax를 이용한 post-it 메모장 만들기(작성, 위치 저장, 삭제)
[ 구현 목표 ]
- 어제 작업하던 post-it 마무리 구현을 오늘 해보자.
1. 메모 이동 -> (id, left, top) -> DB 반영
2. 메모 z-index 변경 -> (id, zindex) -> DB반영
3. 메모 내용 수정 -> (id, memo) -> DB반영
-----------------------------------------------------------
4. 메모 삭제 -> DB반영
--> 정리해서 업무 구분을 하자면 이동, z-index 변경, 내용 수정은 UPDATE 작업이며 메모 삭제는 DELETE 작업이다.
[ 환경설정 및 파일 생성 ]
- 환경설정, 파일 및 DB테이블은 어제와 동일하다.
- https://kyhyuk.tistory.com/156
[ MemoController.java ]
- 이동, z-index변경, 내용 수정(edit) 작업과 메모 삭제(del) 작업을 구분지어 나눈다.
@Controller
public class MemoController {
@Autowired
private AjaxDAO dao;
@RequestMapping(value = "/memo/edit.action", method = { RequestMethod.POST })
@ResponseBody
public int edit(HttpServletRequest req, HttpServletResponse resp, HttpSession session
, MemoDTO dto) {
int result = dao.editMemo(dto);
return result;
}
@RequestMapping(value = "/memo/del.action", method = { RequestMethod.POST })
@ResponseBody
public int delMemo(HttpServletRequest req, HttpServletResponse resp, HttpSession session
, String id) {
int result = dao.delMemo(id);
return result;
}
}
[ MemoDAO.java ]
@Repository
public class MemoDAO {
@Autowired
private SqlSessionTemplate template;
public int editMemo(MemoDTO dto) {
return template.update("ajax.editMemo", dto);
}
public int delMemo(String id) {
return template.delete("ajax.delMemo", id);
}
}
[ MemoDTO.java ]
- 어제와 동일
[ ajax.xml ]
- 수정, 삭제 쿼리문 작성
<mapper namespace="ajax">
<update id="editMemo" parameterType="com.test.ajax.MemoDTO">
update tblAjaxMemo set
left = #{left},
top = #{top},
zindex = #{zindex},
memo = #{memo}
where id = #{id}
</update>
<delete id="delMemo" parameterType="String">
delete from tblAjaxMemo where id = #{id}
</delete>
</mapper>
[ index.jsp ]
- CSS와 HTML은 어제와 동일하며 Script부분이 코드가 많이 지저분해졌다. (리펙토링 필수... 비슷한 코드가 많음)
1) post-it 메모지 추가시 발생하는 이벤트
// 메모지 생성 시 무작위 left값
function getLeft() {
let left = 0;
while (left < 100) {
left = Math.random() * $(document).width() - 250;
}
return left;
}
// 메모지 생성 시 무작위 top값
function getTop() {
let top = 0;
while (top < 100) {
top = Math.random() * $(document).height() - 250;
}
return top;
}
let no = ${no + 1}; // id값
let back = ${back + 1}; // 이미지 파일명
let zindex = ${zindex + 1}; // 클릭한 postit 가장 앞으로
// 버튼 클릭시 새 메모 추가하기
$('#addMemo').click(function() {
// post-it 이미지파일(back)이 6개밖에 없으므로..
if (back > 6) back = 1;
let left = getLeft();
let top = getTop();
$('body').append('<div class="memo" id="m' + no + '" style="background-image: url(/ajax/resources/images/0' + back + '.png);" data-back="0' + back + '"><div class="btnClose">×</div><textarea class="txtMemo" ></textarea></div>')
.children()
.last()
.draggable({
stop: function(event ui) {
let left = ui.position.left;
let top = ui.position.top;
let id = this.id;
let zindex = $(this).css('z-index');
let memo = $(this).find('textarea').val();
$.ajax({
type: 'POST',
url: '/ajax/memo/edit.action',
data: 'left=' + left + '&top=' + top + '&id=' + id + '&zindex=' + zindex + '&memo=' + memo,
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a, b, c) {
console.log(a, b, c);
}
});
}
})
.css('position', 'absolute') // 메모객체
.css('left', left + 'px')
.css('top', top + 'px')
.mousedown(function() { // 메모지 클릭후 이동(메모객체)
$(this).css('z-index', zindex);
let left = parseFloat($(this).css('left'));
let top = parseFloat($(this).css('top'));
let id = this.id;
let memo = $(this).find('textarea').val();
$.ajax({
type: 'POST',
url: '/ajax/memo/edit.action',
data: 'left=' + left + '&top=' + top + '&id=' + id + '&zindex=' + zindex + '&memo=' + memo,
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a, b, c) {
console.log(a, b, c);
}
});
zindex++;
})
.find('.btnClose').click(function() { // 메모객체의 닫기버튼
let id = this.parentNode.id;
$.ajax({
type: 'POST',
url: '/ajax/memo/del.action',
data: 'id=' + id,
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a, b, c) {
console.log(a, b, c);
}
});
$(this).parent().remove();
})
.next().blur(function() { // 메모 객체의 텍스트 박스
let left = parseFloat($(this).parent().css('left'));
let top = parseFloat($(this).parent().css('top'));
let id = this.parentNode.id;
let memo = $(this).val();
$.ajax({
type: 'POST',
url: '/ajax/memo/del.action',
data: 'left=' + left + '&top=' + top + '&id=' + id + '&zindex=' + zindex + '&memo=' + memo,
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a, b, c) {
console.log(a, b, c);
}
});
});
$.ajax({
type: 'POST',
url: '/ajax/memo/add.action',
data: 'id=m' + no + '&background=0' + back + '&left=' + left + '&top=' + top + '&zindex=0',
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a, b, c) {
console.log(a, b, c);
}
});
no++;
back++;
});
2) index.action에 접속했을 때 저장되어 있는 post-it 메모지 출력
<c:forEach items="${list}" var="dto">
$('body').append(`<div class="memo" id="${dto.id}" style="background-image: url(/ajax/resources/images/${dto.background}.png);z-index:${dto.zindex};" data-back="${dto.background}"><div class="btnClose">×</div><textarea class="txtMemo">${dto.memo}</textarea></div>`)
.children()
.last()
.draggable({
stop: function(event, ui) {
let left = ui.position.left;
let top = ui.position.top;
let id = this.id;
let zindex = $(this).css('z-index');
let memo = $(this).find('textarea').val();
$.ajax({
type: 'POST',
url: '/ajax/memo/edit.action',
data: 'left=' + left + '&top=' + top + '&id=' + id + '&zindex=' + zindex + '&memo=' + memo,
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a, b, c) {
console.log(a, b, c);
}
});
}
}) // 메모 객체
.css('position', 'absolute') // 메모객체
.css('left', '${ dto.left }px')
.css('top', '${ dto.top }px')
.mousedown(function() { // 메모객체
$(this).css('z-index', zindex);
let left = parseFloat($(this).css('left'));
let top = parseFloat($(this).css('top'));
let id = this.id;
let memo = $(this).find('textarea').val();
$.ajax({
type: 'POST',
url: '/ajax/memo/edit.action',
data: 'left=' + left + '&top=' + top + '&id=' + id + '&zindex=' + zindex + '&memo=' + memo,
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a, b, c) {
console.log(a, b, c);
}
});
zindex++;
})
.find('.btnClose').click(function() { // 메모객체의 닫기버튼
let id = this.parentNode.id;
$.ajax({
type: 'POST',
url: '/ajax/memo/del.action',
data: 'id=' + id,
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a,b,c) {
console.log(a,b,c);
}
});
$(this).parent().remove();
})
.next().blur(function() { // 메모 객체의 텍스트 박스
let left = parseFloat($(this).parent().css('left'));
let top = parseFloat($(this).parent().css('top'));
let id = this.parentNode.id;
let memo = $(this).val();
$.ajax({
type: 'POST',
url: '/ajax/memo/edit.action',
data: 'left=' + left + '&top=' + top + '&id=' + id + '&zindex=' + zindex + '&memo=' + memo,
dataType: 'json',
success: function(result) {
if (result == 1) {}
else {}
},
error: function(a,b,c) {
console.log(a,b,c);
}
});
});
</c:forEach>
[ Sciprt 정리 ]
- 오늘 수업을 진행하면서 매우 비슷한 코드가 많이 발생해 코드가 많이 지저 분해졌는데, 리펙토링은 따로 할 예정이며 우선 코드별 업무를 구분하여 정리하기
[ 결과 화면 ]
- post-it 생성 후 마우스를 클릭 후 이동한 뒤 메모 작성은 물론 삭제 및 수정도 정상적으로 작동하며, DB에 ajax를 통해 새로고침없이 반영이 되어 새로고침을 하더라도 현재 이동한 위치와 내용이 그대로 남아있는것을 볼 수 있다.
[ 참고 document ]
- https://api.jqueryui.com/draggable/#event-stop
MEMO>
# 이전에도 느꼈지만, 오늘 ajax를 사용하면서 사용자의 관점으로 브라우저를 사용한다고 생각했을 떄 매우 자연스럽고 편리하다는걸 깨달았다. 한편으로는 개발자는 힘들겠다라는 것도 깨달았다....
# 구글링을 통해 지식을 얻는것도 좋지만, 내가 사용하는 API에 대해 100% 정확히 나와있는것은 document 이므로 document를 먼저 보는 습관을 기르자
# 많이 꼬여있는 선처럼 복잡할 것 같은 구현도 하나씩 해나가면 결국엔 할 수 있다!
728x90
반응형
'교육 > Spring' 카테고리의 다른 글
Spring 개발자 수업 110일차(2) - RESTful API (0) | 2021.09.02 |
---|---|
Spring 개발자 수업 110일차(1) - RESTful API (0) | 2021.09.02 |
Spring 개발자 수업 108일차 - jQuery Ajax를 이용한 post-it 메모장 만들기(생성, 확인) (0) | 2021.08.30 |
Spring 개발자 수업 107일차 - 휴강 (0) | 2021.08.28 |
Spring 개발자 수업 105일차(2) - jQuery Ajax를 이용한 아이디 중복검사 (0) | 2021.08.26 |
댓글