diff --git a/README.md b/README.md index e97a1d649..5bbb7263a 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,24 @@ ### 지하철 노선도 출력 기능 - 지하철 노선도 출력 버튼을 누르면 `
` 태그를 만들고 해당 태그 내부에 노선도를 출력한다. + +## 기능목록 단위 +- 지하철 역 이름을 입력받아 역 목록에 추가한다. + - 중복된 역 이름이 추가될 수 없다. +- 역 목록에서 지하철역을 삭제할 수 있다. +- 역 목록에서 지하철역이 삭제되면 이후 select element에서도 삭제된다. +- 지하철 노선을 추가할 수 있다. + - 상행 종점과 하행 종점을 선택한다. +- 노선 목록에서 노선을 삭제할 수 있다. +- 노선을 선택하여 원하는 위치에 구간을 추가할 수 있다. + - 추가할 위치는 음수가 될 수 없다. +- 노선에서 원하는 구간을 제거할 수 있다. + - 제거 버튼을 누르면 제거할 것인지 확인하는 경고창을 띄운다 + - 경고창에서 확인을 눌러야 구간이 제거된다. +- 노선 이름과 노선에 포함된 구간들을 출력한다. +- 새로고침 해도 데이터가 삭제되지 않는다. + + ### 기존 요구사항 - 사용자가 잘못된 입력 값을 작성한 경우 `alert`을 이용해 메시지를 보여주고, 재입력할 수 있게 한다. diff --git a/index.html b/index.html index fc99deac2..f4d60ca48 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,61 @@

🚇 지하철 노선도 관리

+ + + +

+ + + + + + + diff --git a/src/index.js b/src/index.js index e69de29bb..5aad3ff10 100644 --- a/src/index.js +++ b/src/index.js @@ -0,0 +1,351 @@ +import {Line} from "./line.js"; +import {Section} from "./section.js"; +import {addStationToArray, addLineToArray, + addStationToSectionArray, deleteLineFromArray, deleteStationFromArray, removeStationFromSectionArray} from "./localStorage.js" + +window.arrStations = new Array(); +window.arrLine = new Array(); +GetStationsArray(); +GetLinesArray(); + +const eachStation = document.getElementById('#station-name-input').value; +const addStationBtn = document.getElementById('#station-add-button'); +addStationBtn.addEventListener('click', addStationToTable); + +const addStationToSectionButton = document.getElementById('#section-add-button'); +addStationToSectionButton.addEventListener('click', addStationToSection); + +const addLineBtn = document.getElementById('#line-add-button'); +addLineBtn.addEventListener('click', addLineToTable); + +let manageStations = document.getElementById('#station-manager-button'); +let manageLines = document.getElementById('#line-manager-button'); +let manageSections = document.getElementById('#section-manager-button'); +let printSubwaymap = document.getElementById('#map-print-manager-button'); + +manageStations.addEventListener('click', showManageStations); +manageLines.addEventListener('click', showManageLines); +manageSections.addEventListener('click', showManageSections); +printSubwaymap.addEventListener('click', showSubwaymap); + +function GetStationsArray() { + if(localStorage.getItem("stations") != null) { + arrStations = JSON.parse(localStorage.getItem("stations")); + for(let i = 0; i < arrStations.length; i++) { + createStationHTML(arrStations[i]); + } + } +} + +function GetLinesArray() { + if(localStorage.getItem("lines") != null) { + arrLine = JSON.parse(localStorage.getItem("lines")); + for(let i=0; i < arrLine.length; i++) { + makeTableOfLine(arrLine[i]); + let length = arrLine [i].section.stations.length; + if(length > 0) { + createLineHTML(arrLine[i], arrLine[i].name, + arrLine[i].section.stations[0], arrLine[i].section.stations[length - 1]); + createStationInSectionHTML(arrLine[i]); + } + } + } +} + +function addStationToTable() { + + let stationName = document.getElementById('#station-name-input').value; + + let index = arrStations.indexOf(stationName); + if(index != -1) { + alert('같은 역 이름을 입력할 수 없습니다.'); + return; + } + + createStationHTML(stationName); + addStationToArray(stationName); +} + +function createStationHTML(stationName) { + let stationTable = document.getElementById('#print-station-list'); + let stationRow = stationTable.insertRow(stationTable.rows.length); + let cell1 = stationRow.insertCell(0); + cell1.innerHTML = stationName; + + let deleteButton = addStationDeleteBtnOnTable(stationRow); + deleteStationFromTable(deleteButton); + addOptionsToSelectBox(stationName); + document.getElementById('#station-name-input').value=''; + addOptionsToSectionSelectBox(stationName); +} + +function addStationDeleteBtnOnTable(stationRow) { + let cell2 = stationRow.insertCell(1); + let stationDeleteBtn = document.createElement('button'); + let stationDeleteBtnText = document.createTextNode('삭제'); + stationDeleteBtn.className = '.station-delete-button'; + stationDeleteBtn.appendChild(stationDeleteBtnText); + document.body.appendChild(stationDeleteBtn); + cell2.appendChild(stationDeleteBtn); + + return stationDeleteBtn; +} + +function addOptionsToSelectBox(stationName) { + //first station + let selectStationStart = document.getElementById("#line-start-station-selector"); + let elStart = document.createElement("option"); + elStart.textContent = stationName; + elStart.value = stationName; + selectStationStart.appendChild(elStart); + //last station + let selectStationEnd = document.getElementById("#line-end-station-selector"); + let elEnd = document.createElement("option"); + elEnd.textContent = stationName; + elEnd.value = stationName; + selectStationEnd.appendChild(elEnd); +} + +function deleteStationFromTable(deleteButton) { + //connect delete function to the delete button + deleteButton.addEventListener('click', function() { + let arrButton = document.getElementsByClassName('.station-delete-button'); + let stationSelector = document.getElementById('#line-start-station-selector'); + let endStationSelector = document.getElementById('#line-end-station-selector'); + let index = [].slice.call(arrButton).indexOf(deleteButton); + stationSelector.remove(index); + endStationSelector.remove(index); + + deleteStationFromArray(index); + + this.parentElement.parentElement.remove(); + }); +} + +function addLineToTable() { + let lineName = document.getElementById('#line-name-input').value; + let firstStation = document.getElementById('#line-start-station-selector').value; + let lastStation = document.getElementById('#line-end-station-selector').value; + let newLine = new Line(lineName, firstStation, lastStation); + + addLineToArray(newLine); + + createLineHTML(newLine, newLine.name, firstStation, lastStation); +} + +function createLineHTML(newLine, lineName, firstStation, lastStation) { + let lineTable = document.getElementById('#print-line-list'); + let lineRow = lineTable.insertRow(lineTable.rows.length); + let cell1 = lineRow.insertCell(0); + let cell2 = lineRow.insertCell(1); + let cell3 = lineRow.insertCell(2); + cell1.innerHTML = lineName; + cell2.innerHTML = firstStation; + cell3.innerHTML = lastStation; + document.getElementById('#line-name-input').value=''; + + let deleteButton = addLineDeleteBtnOnTable(lineRow); + makeLineBtnFromArray(newLine); + deleteLineFromTable(deleteButton, newLine); + makeTableOfLine(newLine); +} + +function addLineDeleteBtnOnTable(lineRow) { + //add delete button on the table + let lineDeleteBtn = document.createElement('button'); + let lineDeleteBtnText = document.createTextNode('삭제'); + let cell4 = lineRow.insertCell(3); + lineDeleteBtn.className = '.line-delete-button'; + lineDeleteBtn.appendChild(lineDeleteBtnText); + document.body.appendChild(lineDeleteBtn); + cell4.appendChild(lineDeleteBtn); + + return lineDeleteBtn; +} + +function deleteLineFromTable(deleteLineButton, newLine) { + //connect delete function to the delete button + deleteLineButton.addEventListener('click', function() { + const index = arrLine.indexOf(newLine); + //arrLine.splice(index,1); + deleteLineFromArray(index); + this.parentElement.parentElement.remove(); + makeSubwayMap(); + }); +} + +function makeLineBtnFromArray(newLine) { + let lineBtn = document.createElement('button'); + let lineBtnText = document.createTextNode(newLine.name); + lineBtn.appendChild(lineBtnText); + lineBtn.className = '.section-line-menu-button'; + document.getElementById('line-buttons').appendChild(lineBtn); + + lineBtn.addEventListener('click', function() {showAddDeleteSection(newLine)}); +} + +function addOptionsToSectionSelectBox(stationName) { + let selectSection = document.getElementById('#section-station-selector'); + let elSection = document.createElement('option'); + elSection.textContent = stationName; + elSection.value = stationName; + selectSection.appendChild(elSection); +} + +function makeTableOfLine(newLine) { + let container = document.getElementById('section-lists-container'); + let sectionTable = document.createElement('table'); + + let headerRow = sectionTable.insertRow(0); + let headerCell1 = headerRow.insertCell(0); + let headerCell2 = headerRow.insertCell(1); + let headerCell3= headerRow.insertCell(2); + headerCell1.innerHTML = '순서'; + headerCell2.innerHTML = '이름'; + headerCell3.innerHTML = '설정'; + + sectionTable.id = '#print-section-list-' + newLine.name; + sectionTable.border = 1; + sectionTable.classList.add('section-table'); + sectionTable.style.width = 'fit-content'; + + let lengthOfStations = newLine.section.stations.length; + for (let i = 0; i < lengthOfStations; i += 1) { + addLineToSectionTable(sectionTable, newLine.section.stations[i], i); + } + makeSubwayMap(); + container.appendChild(sectionTable); +} + +function addLineToSectionTable(sectionTable, sectionName, sectionOrder) { + let sectionRow = sectionTable.insertRow(sectionOrder + 1); + let sectionCell1 = sectionRow.insertCell(0); + let sectionCell2 = sectionRow.insertCell(1); + let sectionCell3= sectionRow.insertCell(2); + sectionCell1.innerHTML = sectionOrder; + sectionCell2.innerHTML = sectionName; + addSectionDeleteBtn(sectionTable, sectionCell3); +} + +function addSectionDeleteBtn(sectionTable, sectionCell3) { + let sectionDeleteBtn = document.createElement('button'); + let sectionDeleteBtnText = document.createTextNode('노선에서 제거'); + sectionDeleteBtn.className = '.section-delete-button'; + sectionDeleteBtn.appendChild(sectionDeleteBtnText); + document.body.appendChild(sectionDeleteBtn); + sectionCell3.appendChild(sectionDeleteBtn); + + sectionDeleteBtn.addEventListener('click', function() { + if(confirm('정말로 노선에서 제거하시겠습니까?')) { + let index = this.parentElement.parentElement.rowIndex - 1; + let lineName = document.getElementById('selected-line-input').value; + let lineIndex = arrLine.findIndex(l => l.name == lineName); + let line = arrLine[lineIndex]; + + removeStationFromSectionArray(line, index); + + for(let i = sectionTable.rows.length - 1; i > 0; i--){ + sectionTable.deleteRow(i); + } + + for (let i = 0; i < line.section.stations.length; i++) { + addLineToSectionTable(sectionTable, line.section.stations[i], i); + } + makeSubwayMap(); + } else { + + } + }); +} + +function makeSubwayMap() { + document.getElementsByClassName('map')[0].innerHTML = ''; + let tag = ''; + + for(let i = 0; i < arrLine.length; i++) { + tag += getLineMap(arrLine[i]); + tag += '
'; + } + + document.getElementsByClassName('map')[0].innerHTML += tag; +} + +function getLineMap(line) { + let tag = ''; + tag += '

' + line.name + "

"; + + tag += ''; + + return tag; +} + +function addStationToSection() { + let station = document.getElementById('#section-station-selector').value; + let index = parseInt(document.getElementById('#section-order-input').value); + let lineName = document.getElementById('selected-line-input').value; + + let lineIndex = arrLine.findIndex(l => l.name == lineName); + let line = arrLine[lineIndex]; + + addStationToSectionArray(line, station, index); + createStationInSectionHTML(line); +} + +function createStationInSectionHTML(line) { + let sectionTable = document.getElementById('#print-section-list-' + line.name); + for(let i = sectionTable.rows.length - 1; i > 0; i--){ + sectionTable.deleteRow(i); + } + + for (let i = 0; i < line.section.stations.length; i++) { + addLineToSectionTable(sectionTable, line.section.stations[i], i); + } + + makeSubwayMap(); +} + +function showManageStations() { + document.getElementById('station-manager').style.display = 'block'; + document.getElementById('line-manager').style.display = 'none'; + document.getElementById('section-manager').style.display = 'none'; + document.getElementsByClassName('map')[0].style.display = 'none'; +} + +function showManageLines() { + document.getElementById('line-manager').style.display = 'block'; + document.getElementById('station-manager').style.display = 'none'; + document.getElementById('section-manager').style.display = 'none'; + document.getElementsByClassName('map')[0].style.display = 'none'; +} + +function showManageSections() { + document.getElementById('section-manager').style.display = 'block'; + document.getElementById('station-manager').style.display = 'none'; + document.getElementById('line-manager').style.display = 'none'; + document.getElementsByClassName('map')[0].style.display = 'none'; +} + +function showSubwaymap() { + document.getElementsByClassName('map')[0].style.display = 'block'; + document.getElementById('station-manager').style.display = 'none'; + document.getElementById('line-manager').style.display = 'none'; + document.getElementById('section-manager').style.display = 'none'; +} + +function showAddDeleteSection(newLine) { + document.getElementById('add-delete-section').style.display = 'block'; + document.getElementById('nline-manage').innerHTML = `${newLine.name} 관리`; + + let lineSectionTables = document.getElementsByClassName('section-table'); + + for(let i = 0; i < lineSectionTables.length; i++) { + lineSectionTables[i].style.display = 'none'; + } + + document.getElementById('#print-section-list-' + newLine.name).style.display = 'block'; + document.getElementById('selected-line-input').value = newLine.name; +} \ No newline at end of file diff --git a/src/line.js b/src/line.js new file mode 100644 index 000000000..a5c1e6a97 --- /dev/null +++ b/src/line.js @@ -0,0 +1,8 @@ +import { Section }from './section.js' + +export class Line { + constructor(name, firstStation, lastStation) { + this.name = name; + this.section = new Section(firstStation, lastStation); + } +} \ No newline at end of file diff --git a/src/localStorage.js b/src/localStorage.js new file mode 100644 index 000000000..01a632bb8 --- /dev/null +++ b/src/localStorage.js @@ -0,0 +1,29 @@ +export function addStationToArray(newStation) { + arrStations.push(newStation); + localStorage.setItem("stations",JSON.stringify(arrStations)); +} + +export function deleteStationFromArray(index) { + arrStations.splice(index,1); + localStorage.setItem("stations",JSON.stringify(arrStations)); +} + +export function addLineToArray(newLine) { + arrLine.push(newLine); + localStorage.setItem("lines",JSON.stringify(arrLine)); +} + +export function deleteLineFromArray(index) { + arrLine.splice(index,1); + localStorage.setItem("lines",JSON.stringify(arrLine)); +} + +export function addStationToSectionArray(line, station, index) { + line.section.stations.splice(index,0, station); + localStorage.setItem("lines",JSON.stringify(arrLine)); +} + +export function removeStationFromSectionArray(line, index) { + line.section.stations.splice(index,1); + localStorage.setItem("lines",JSON.stringify(arrLine)); +} diff --git a/src/section.js b/src/section.js new file mode 100644 index 000000000..e4de00aac --- /dev/null +++ b/src/section.js @@ -0,0 +1,15 @@ +export class Section { + constructor(firstStation, lastStation) { + this.stations = []; + this.stations.push(firstStation); + this.stations.push(lastStation); + } + + addStation(station, position) { + this.stations.splice(position, 0, station); + } + + deleteStation() { + this.stations.splice(position, 1); + } +} \ No newline at end of file