안녕하세요 프로그래밍 맛보기 3부로 왔습니다.
1부에서는 프로그래밍의 Basic 개념에 대해 다루었었습니다
2부에서는 객체 지향 프로그래밍에서 중요한 개념인 Class에 대해 배웠었습니다
그리고 이번 3부에서는 우리가 공부한 것들을 바탕으로 서비스 단위 개발을 맛보기로 해볼까 합니다
2부에 작성했던 업무모델 로직을 바탕으로 진행하겠습니다.
여기에 서비스 화면UI, 서비스 처리 로직을 조금 더하여 만들어보겠습니다.
이번에도 메모장을 열어 다음 코드를 함께 작성하시겠습니다.
<script type="text/javascript">
//----- 서비스에 사용될 Data들 ---------------------------------------------------------------------------------------------------
var employees = [ //시스템에 등록된 사원목록
{
employee_id: '12345',
name: '소영희',
position: '대리',
working_months: 36,
salary: 4000
},
{
employee_id: '67890',
name: '장경식',
position: '과장',
working_months: 52,
salary: 5300
},
{
employee_id: '14703',
name: '정명준',
position: '차장',
working_months: 85,
salary: 6000
}
];
var tasks = [ //시스템에 등재된 업무목록
{
task_id: '54321',
task: 'xx프로젝트 팀원',
working_hours: 42,
person_in_charge: '67890'
},
{
task_id: '09876',
task: 'xx프로젝트 영업지원',
working_hours: 57,
person_in_charge: '12345'
}
];
</script>
<!----- 서비스 화면UI ------------------------------------------------------------------------------------------------------->
<div class="data">
<div class="dataTitle" >
<b>[ㅇㅇ모직 직원목록]</b>
</div>
<table cellpadding="0" cellspacing="0" style="text-align:center;">
<thead>
<tr>
<th></th><th>사번</th><th>이름</th><th>직위</th><th>근무개월수</th><th>연봉</th><th>담당업무명</th><th>공수</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="8">결과를 조회 중입니다</td>
</tr><!--
<tr>
<td>b</td><td>b</td><td>b</td><td>b</td><td>b</td><td>b</td><td>b</td>
</tr>
<tr>
<td>c</td><td>c</td><td>c</td><td>c</td><td>c</td><td>c</td><td>c</td>
</tr>
<tr>
<td>d</td><td>d</td><td>d</td><td>d</td><td>d</td><td>d</td><td>d</td>
</tr>-->
</tbody>
</table>
<div>
<button onclick="hrd.showEmployeeInfoModal('add')" >등록</button>
<button onclick="hrd.showEmployeeInfoModal('modify')" >수정</button>
<button onclick="hrd.deleteEmployeeInfoById()" >삭제</button>
</div>
</div>
<!-- The Modal -->
<div id="myModal" class="fade-bg">
<!-- Modal content -->
<div class="modal-content">
<div class="close" style="float:right">×</div>
<p id="modalTitle1" class="modalTitle" style="float:left;"><b>사원 등록/수정</b></p>
<form><!-- serialize -->
<table>
<tr>
<th width="30"></th><th width="100"></th><th></th>
</tr>
<tr>
<td></td>
<td>사번</td><td><input type="text" name="employee_id"></td>
</tr>
<tr>
<td></td>
<td>이름</td><td><input type="text" name="name"></td>
</tr>
<tr>
<td></td>
<td>직위</td><td><input type="text" name="position"></td>
</tr>
<tr>
<td></td>
<td>근무개월수</td><td><input type="text" name="working_months"></td>
</tr>
<tr>
<td></td>
<td>연봉</td><td><input type="text" name="salary"></td>
</tr>
<tr>
<td></td>
<td colspan="2">
<button type="button" id="modalBtn" onclick="" >등록</button>
<button type="button" onclick="showModal('N')" >취소</button>
</td>
</tr>
</table>
</form>
</div>
</div>
<!-- The Loader -->
<div id="myLoader" class="fade-bg">
<div class="loader"></div>
</div>
<style type="text/css">
button { float:left;width:150;padding:10 10;margin:30 20; }
.data { padding:30 100;width:600 }
.dataTitle { font-size:15pt;padding:20 0; }
div.data table { text-align:center;width:850; }
div.data table th { padding:10 15;background-color:black;color:white; }
div.data table td { padding:10 15; }
div.data tr:nth-child(n) td { background-color:lightgrey;border-bottom:1px solid grey; }
.modalTitle { font-size:15pt;padding-left:20; }
div.modal-content table { clear:both;padding-top: 15; }
div.modal-content table th {}
div.modal-content table td { padding:5; }
div.modal-content tr:nth-child(n) td {}
/* The Modal (background) */
.fade-bg {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content/Box */
.modal-content {
background-color: #fefefe;
margin: 5% 15%; /* 15% from the top, to center use auto */
padding: 20px;
border: 1px solid #888;
width: 470px; /* Could be more or less, depending on screen size */
}
/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
/* Loader */
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 80px; height: 80px;
animation: spin 2s linear infinite;
margin: 180 480;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
//Loader 소스 출처. w3schools https://www.w3schools.com/howto/howto_css_loader.asp
</style>
<script type="text/javascript">
try {
//----- 서비스 처리 로직 ---------------------------------------------------------------------------------------------------------
window.onload = function() {
console.log("onload-start:"+ (performance.now()/1000).toFixed(5) +" sec"); //수행시간 측정 시작
hrd.loadDataToTable();
console.log("onload-ended:"+ (performance.now()/1000).toFixed(5) +" sec"); //수행시간 측정 종료
}
//employees.length = [];
var table = document.getElementsByTagName("table")[0];
var buttons = document.getElementsByTagName("button");
var hrd = {
//----- 추가된 기능 --------------------------------------------------------------------------------------------------------------
loadDataToTable: function() {
table.getElementsByTagName("tbody")[0].innerHTML="";
if(employees.length>0) {
for(var i=0; i<employees.length; i++) {
var row = "<tr>"
+"<td>"+"<input type='checkbox' value='"+employees[i].employee_id+"'>"+"</td>"
+"<td>"+employees[i].employee_id+"</td>"
+"<td>"+getMaskedName(employees[i].name)+"</td>"
+"<td>"+employees[i].position+"</td>"
+"<td>"+employees[i].working_months+"</td>"
+"<td>"+employees[i].salary+"</td>"
var hastask = false;
for(var j=0; j<tasks.length; j++) {
if (employees[i].employee_id == tasks[j].person_in_charge) {
hastask = true;
row+= "<td>"+tasks[j].task+"</td>"
+"<td>"+tasks[j].working_hours+"</td>";
}
}
if(!hastask) row+= "<td>"+"업무 미배정"+"</td>"+"<td>"+"</td>";
row+= "<tr>";
table.getElementsByTagName("tbody")[0].innerHTML+=row;
}
} else {
table.getElementsByTagName("tbody")[0].innerHTML+=
"<tr><td colspan='8'>등록된 직원이 없습니다</td></tr>";
for(var i=0; i<buttons.length ; i++) {
buttons[i].disabled = true;
}
}
},
verifyEmployeeInfoById: function(emp_id){
var targetEmployee = this.getEmployeeInfoById(emp_id);
if(targetEmployee=="not registered") {
return "등록되지 않은 사번입니다";
}
else {
return targetEmployee;
}
},
showEmployeeInfoModal: function(command){
var modalBtn = document.getElementById("modalBtn");
if(command == "add") {
showModal("Y");
modalTitle1.innerHTML = "<b>사원정보 등록</b>";
modalBtn.innerHTML = "등록";
modalBtn.onclick = function() { hrd.addEmployeeInfo(''); };
}
else if(command == "modify") {
alert("수정 기능 준비중입니다");
//showModal("Y");
//modalTitle1.innerHTML = "<b>사원정보 수정</b>";
//modalBtn.innerHTML = "수정";
//modalBtn.onclick = function() { hrd.modifyEmployeeInfoById(''); };
}
},
addEmployeeInfo: function(emp_id){
var employee = this.setValidEmployee();
if(employee == "notValid") return;
console.log("hrd.addEmployeeInfo-start:" + (performance.now()/1000).toFixed(2) +" sec"); //수행시간 측정 시작
var thisclass = this;
showLoader("Y");
setTimeout(function() {
employees.push(employee);
thisclass.loadDataToTable();
showLoader("N");
thisclass.afterTask("사원정보를 성공적으로 등록하였습니다");
console.log("hrd.addEmployeeInfo-ended:"+ (performance.now()/1000).toFixed(2) +" sec"); //수행시간 측정 종료
}, 1200);
},
//숙제. 수정 기능을 구현해보세요
modifyEmployeeInfoById: function(emp_id){
alert("수정 기능 준비중입니다");
this.afterTask("사원정보를 성공적으로 수정하였습니다");
},
setValidEmployee() {
var employee_id = document.querySelector("input[name=employee_id]");
var name = document.querySelector("input[name=name]");
var position = document.querySelector("input[name=position]");
var working_months = document.querySelector("input[name=working_months]");
var salary = document.querySelector("input[name=salary]");
//serialize
var form = document.getElementsByTagName("form")[0]; var data = new FormData(form);
var dataObj = {}; for(let entry of data){ dataObj[entry[0]]=entry[1]; } var jsonData = JSON.stringify(dataObj); var jsonObj = JSON.parse(jsonData);
var params = new URLSearchParams(data).toString();
//var req = new XMLHttpRequest(); req.send(data); //send post request
var employee_id_val = employee_id.value; //jsonObj.employee_id;
var name_val = name.value;
var position_val = position.value;
var working_months_val = working_months.value;
var salary_val = salary.value;
var regex = /^[ㄱ-ㅎ|가-힣|a-z|A-Z|]+$/;
if(employee_id_val=="") {
alert("사원번호를 입력하지 않았습니다"); employee_id.focus(); return "notValid"; }
else if(isNaN(employee_id_val)) {
alert("사원번호는 숫자만 사용가능합니다"); employee_id.focus(); return "notValid"; }
if(name_val=="") {
alert("이름을 입력하지 않았습니다"); name.focus(); return "notValid"; }
else if(!regex.test(name_val)) {
alert("이름은 문자만 사용가능합니다"); name.focus(); return "notValid"; }
if(position_val=="") {
alert("직급을 입력하지 않았습니다"); position.focus(); return "notValid"; }
else if(!regex.test(position_val)) {
alert("직급은 문자만 사용가능합니다"); position.focus(); return "notValid"; }
if(working_months_val=="") {
alert("근무개월수를 입력하지 않았습니다"); working_months.focus(); return "notValid"; }
else if(isNaN(working_months_val)) {
alert("근무개월수는 숫자만 입력 가능합니다"); working_months.focus(); return "notValid"; }
if(salary_val=="") {
alert("연봉을 입력하지 않았습니다"); salary.focus(); return "notValid"; }
else if(isNaN(salary_val)) {
alert("연봉은 숫자만 입력 가능합니다"); salary.focus(); return "notValid"; }
var employee = new Object();
employee.employee_id = employee_id_val;
employee.name = name_val;
employee.position = position_val;
employee.working_months = working_months_val;
employee.salary = salary_val;
return employee;
},
afterTask(message) {
alert(message);
showModal("N");
},
deleteEmployeeInfoById: function(emp_id){
var target = "";
if(emp_id==null) target = document.querySelectorAll('input[type="checkbox"]:checked');
else target = emp_id;
for(var i=0; i<target.length; i++) {
var verifyResult = ( emp_id==null ? this.verifyEmployeeInfoById(target[i].value) : this.verifyEmployeeInfoById(target) );
if(verifyResult != "등록되지 않은 사번입니다") {
var confimResult = prompt("사원 '"+getMaskedName(verifyResult)+"을 삭제하시겠습니까? 예 / 아니오");
if(confimResult == "예") {
var targetIndex = employees.map((emp) => emp.name).indexOf(verifyResult);
employees.splice(targetIndex, 1);
this.loadDataToTable();
}
}
else {
alert(verifyResult);
}
}
},
//----- 기존의 기능 --------------------------------------------------------------------------------------------------------------
getEmployeeInfoById: function(emp_id){ //사번으로 직원정보를 조회하는 함수
for(var i=0; i<employees.length; i++) {
if (employees[i].employee_id == emp_id) {
return employees[i].name;
/*(
"사번:"+employees[i].employee_id+", "+
"이름:"+employees[i].name+", "+
"직위:"+employees[i].position+", "+
"근무개월수:"+employees[i].working_months+", "+
"연봉:"+employees[i].salary
);*/
}
}
return "not registered";
},
getEmployeesTaskById: function(emp_id){ //사번으로 직원 담당업무를 조회하는 함수
for(var i=0; i<tasks.length; i++) {
if (tasks[i].person_in_charge == emp_id) {
return (
"업무코드:"+tasks[i].task_id+", "+
"업무명:"+tasks[i].task+", "+
"공수:"+tasks[i].working_hours+", "+
"담당직원:"+tasks[i].person_in_charge
);
}
}
return "할당된 업무가 없습니다";
}
};
function getMaskedName(target_name) {
return target_name.replace(/(?<=.{1})./gi, "*");
}
//Modal
var modal = document.getElementById("myModal"); // Get the modal
var span = document.getElementsByClassName("close")[0]; // Get the <span> element that closes the modal
function showModal(toggle_YN) {
if(toggle_YN == "Y") modal.style.display = "block"; // When the user clicks on the button, open the modal
else if(toggle_YN == "N") modal.style.display = "none"; // When the user clicks on <span> (x), close the modal
}
span.onclick = function () { showModal("N"); };
window.onclick = function(event) { // When the user clicks anywhere outside of the modal, close it
if (event.target == modal) modal.style.display = "none";
}
//모달 소스 출처. w3schools https://www.w3schools.com/howto/howto_css_modals.asp
//Loader
var loader = document.getElementById("myLoader");
function showLoader(toggle_YN) {
if(toggle_YN == "Y") loader.style.display = "block";
else if(toggle_YN == "N") loader.style.display = "none";
}
//document.getElementById("b").value;
} catch(e) { console.dir(e); }
</script>
여기까지 작성/저장하시고 .html 파일을 열면, 다음과 같은 화면이 출력될 것입니다.
메모장 대신에 html 소스를 출력해주는 사이트를 이용할 수도 있습니다.
대표적으로
w3schools( https://www.w3schools.com/html/tryit.asp?filename=tryhtml_default ) 이나
jsbin( https://jsbin.com/?html,output )이 있겠습니다.
참고로 정보 수정 기능은 여러분의 몫으로 남겨두어 구현하지 않았습니다.
혹시 여러분은 프로그래밍 하고 싶은 것이 있나요?
사실 개발은 이런 기대들로부터 시작된답니다.
프로그램 맛보기 시리즈가 여러분께 도움이 되셨기를 바랍니다.
좋은 하루되세요.
-----------------------------------------------------------------------------------------------------------------------------------
추가로 data 부분을 다른 파일로 나눠 사용할 수도 있습니다.
data 부분을 data.js로 옮기고, 개발연습.html 에는 아래 외부스크립트를 추가하는 링크를 연결하여 적용이 가능합니다.
개발연습.html
<script type="text/javascript" src="data.js"></script>
data.js
//----- 서비스에 사용될 Data들 ---------------------------------------------------------------------------------------------------
var employees = [ //시스템에 등록된 사원목록
{
employee_id: '12345',
name: '소영희',
position: '대리',
working_months: 36,
salary: 4000
},
{
employee_id: '67890',
name: '장경식',
position: '과장',
working_months: 52,
salary: 5300
},
{
employee_id: '14703',
name: '정명준',
position: '차장',
working_months: 85,
salary: 6000
}
];
var tasks = [ //시스템에 등재된 업무목록
{
task_id: '54321',
task: 'xx프로젝트 팀원',
working_hours: 42,
person_in_charge: '67890'
},
{
task_id: '09876',
task: 'xx프로젝트 영업지원',
working_hours: 57,
person_in_charge: '12345'
}
];
'웹개발 > 개론' 카테고리의 다른 글
웹개발자 필수 소양 (0) | 2022.02.24 |
---|---|
프로그래밍 맛보기(2부) (0) | 2021.07.15 |
프로그래밍 맛보기(1부) (1) | 2021.07.13 |
JAVA 기본 문법 (0) | 2019.12.21 |
개발(프로그래밍)에 대하여 (0) | 2019.12.21 |