- JavaScript
- HTML에서 JavaScript 사용
- 변수
- 자료형 : 7가지
- 자료 구조 - 객체
- 자료 구조 - 배열
- 자료 구조 - 집합
- 자료구조 - Hashtable
- 자료 구조 - Function
- 화면 크기
- 데이터 비교 화면 설계
- Chart Library
- 주요 지도 API
- Table
- Gauge
- 참고 문헌
JavaScript
HTML에서 JavaScript 사용
변수
'use strict'; //--- 엄격한 변수 선언 확인
const 상수 = '~'; //--- 상수
let 변수 = '~'; //--- 가장 가까운 블록 범위내에서 사용
var 변수 = '~'; //--- 가장 가까운 함수 범위내에서 사용
자료형 : 7가지
boolean : 논리
true : true, 0이 아닌 숫자, ''이 아닌 문자열, 비어 있지 않은 객체
false : false, 0, '', NaN, undefined, null
== : 값을 비교 (boolean, number, string에서 사용)
=== : 자료형과 값을 비교
number : 숫자
64 bits 부동소수점
반올림 오류 발생
연산자 : +, -, *, /, %
Math
Math.floor(~) : 내림
Math.round(~) : 반올림
Math.ceil(~) : 올림
Math.trunc(~) : 정수 부분만 반환
Math.random() : 0 < ~ < 1
난수 배열 생성
[] = crypto.getRandomValues(new Uint16Array(10))
[] = crypto.getRandomValues(new Uint32Array(10))
Math.floor(Math.random() * 101) : 0 ~ 100 (정수)
Number
Number.MAX_SAFE_INTEGER : 최대 정수 (양수)
Number.MIN_SAFE_INTEGER : 최소 정수 (음수)
Number.MAX_VALUE : 최대 실수 (양수)
Number.MIN_VALUE : 최소 실수 (0과 가장 가까운 음수)
문자열 = 숫자.toFixed(소수점 자리수)
문자열 = 숫자.toPrecision(전체 자리수)
string : 문자열
String
Array.from(문자열).length : 문자열의 길이
ReqExp : 정규 표현식
선언 : /~/gi, new RegExp('~', 'gi')
문자열 = 문자열.padStart(전체길이, ' ')
문자열 = 문자열.padEnd(전체길이, '0')
btoa('~') : Base64 인코딩
atob('~') : Base64 디코딩
object
undefined : 선언만되고 할당되지 않은 변수
function : 함수
arguments : 전달되는 인수 배열
prototype 속성 : 상속을 위해 사용하는 속성
child.prototype = Object.create(parent.prototype); : 상속
var 변수 : 외부에서 참조 불가
this 속성 : 외부에서 참조 가능
func.call(this, ~) : this를 지정한 후 함수를 호출 한다.
func.apply(this, 배열) : this를 지정한 후 배열의 item을 arguments하여 함수를 호출 한다.
symbol : 심볼
NaN
null
Infinity : 가장 큰 숫자 (무한)
-Infinity : 가장 작은 숫자
typeof ~ //--- 변수의 자료형 확인
//--- undefined : Undefined
//--- string : String
//--- number : Number
//--- boolean : Boolean
//--- symbol : Symbol
//--- object : Null
//--- object : 함수 제외
//--- function : 함수
//--- 반올림 오류가 발생하지 않는 숫자 비교
function numberEquals(x, y) {
return Math.abs(x - y) < Number.EPSILON;
}
//--- 문자열 함수
'~'.charAt(n) //--- n번째 문자 (n = 0, 1, 2, 3, ...)
'~'.substring(n, m) //--- n보다 같거나 크고 m보다 작은 문자열
'~'.indesOf('~') //--- -1. 없음, 0 <. 찾은 문자열의 인덱스
'~'.lastIndexOf('~')
'~'.includes('~')
'~'.startsWith('~') //--- true/false
'~'.endsWith('~') //--- true/false
'~'.split(',') //--- 문자열을 ,로 분리되는 문자열 배열로 변환
'~'.replace('old', 'new')
//--- 정규표현식 함수
//--- /\d+/ : 숫자를 포함하는 문자
//--- /^\d+$/ : 정수
//--- /^[0-9]*.[0-9]*[1-9]+$/ : 실수
//--- /[a-zA-z0-9]/ : 문자와 숫자
'~'.search(/~/) //--- 일치하는 문자열의 인덱스 반환
'~'.match(/~/)
/~/.exec('~') //--- 찾은 첫번째 문자열을 반환
/~/.test('~') //--- true/false
'~'.replace(/~/g, function($0, $1, ...) {
//--- $0 : 찾은 전체 문자열
//--- $1 : 첫번째 ()에 해당하는 문자열
//--- $2 : 두번째 ()에 해당하는 문자열
});
//--- 객체가 가진 속성을 표시
let names = Object.getOwnPropertyNames(obj);
for (let idx = 0; idx < names.length; idx++) {
let name = names[idx];
let value = obj[name]; //--- obj[name] == obj.name
console.log(name, value);
}
자료 구조 - 객체
//--- 선언 : {}, new Object()
//--- 함수를 사용한 객체 선언 : new func()
let data = {};
let dataNew1 = Object.assign({}, data) //--- data를 얕은 복사하여 dataNew1 생성
let dataNew2 = { ...data }; //--- data를 얕은 복사하여 dataNew2 생성
let { key1, key2 } = data; //--- data.key1의 값을 key1으로 복사
data.hasOwnProperty(key)
key in data
Object.keys(data)
Object.values(data)
Object.entries(data) //--- [key, value]의 배열
object : 객체
delete obj.key1;
자료 구조 - 배열
선언 : [], new Array(), new Array(cntItems)
let data = [];
data[n] //--- n번째 항목값 (n = 0, 1, 2, ...)
data.push(~); //--- 마지막 항목 추가
data.pop(); //--- 마지막 항목 꺼내기
data.shift(); //--- 첫번째 항목 꺼내기
data.unshift(~); //--- 첫번째 항목 추가
data.slice(n, m); //--- n보다 같거나 크고 m 보다 작은 항목 배열
//--- 반복문
for (let idx = 0; idx < data.length; idx++) {
let item = data[idx];
}
for (let idx in data) {
let value = data[idx];
}
for (let value of data) {
}
data.forEach(function(item, idx, data) { ~ }); //--- this를 사용할 수 없다.
data.map(function(item) { ~ })
data.reduce(function(prevVal, curVal, idx, array) {
//--- preVal : data[0] 또는 initPrevVal
//--- curVal : data 배열에서 현재값
//--- idx : initPrevVal이 있으면 0부터 시작하고 아니면 1부터 시작
//--- array : data
return ~;
},
initPrevVal); //--- 최초 preVal 값 (생략 가능)
data.filter(function(item) { //--- true인 항목만 배열에 담아 반환
return 100 < item;
});
//--- 배열 함수
let data1 = Array.from(data); //--- 배열 복사
let data2 = data.slice(); //--- 배열 복사
let data3 = data1.concat(data2); //--- data1에 data2를 붙여 반환
//--- data에서 start부터 size만큼 추출한 배열을 반환 한다.
//--- data는 start부터 size만큼 삭제되고, 그 자리에 item1, item2, ...이 포함된다.
data.splice(start, size, item1, item2, ...);
//--- 전개연산자 (...)
func(...data) //--- data의 각 항목이 func 함수의 인수로 전달
정렬과 검색
data.sort(); //--- 문자열을 오름차순 정렬
data.sort(function(a, b) { //--- 숫자를 오름차순 정렬
return a - b; //--- 음수. a < b, 0. a = b, 양수. a > b
});
data.filter(function(item) { //--- 검색
return item == '~';
})
자료 구조 - 집합
let data = new Set();
data.add(~);
data.delete(~);
data.has(~); //--- true/false
for (let item of data) {
}
자료구조 - Hashtable
let hashtable = {};
자료 구조 - Function
function (...names) {
}
화면 크기
브라우저에서 HTML이 표시되는 화면의 크기 : window.innerWidth * window.innerHeight
Body 영역의 크기 : $('body')[0].clientWidth * $('body')[0].clientHeight
영역의 크기 : obj.clientWidth * obj.clientHeight
상위 영역내에서 좌측 상단의 위치 : obj.offsetLeft * obj.offsetTop
$('#contentList').css('border', '1px solid blue');
$('#contentMap').css('border', '1px solid blue');
$('#contentChart').css('border', '1px solid blue');
let content = [];
content.push('전체 화면 크기 : ' + screen.width + ' * ' + screen.height);
content.push('작업 표시줄 크기 : ' + (screen.width - screen.availWidth) + ' * ' + (screen.height - screen.availHeight));
content.push('전체 화면 크기 (작업 표시줄 제외) : ' + screen.availWidth + ' * ' + screen.availHeight);
content.push('----------');
content.push('브라우저 화면 크기 : ' + window.outerWidth + ' * ' + window.outerHeight);
content.push('Tab, URL, 즐겨찾기 등 : ' + (window.outerWidth - window.innerWidth) + ' * ' + (window.outerHeight - window.innerHeight));
content.push('HTML 화면 크기 (개발자 도구 제외) : ' + window.innerWidth + ' * ' + window.innerHeight + '');
content.push('Scroll 크기 : ' + (window.innerWidth - $('html')[0].clientWidth) + ' * ' + (window.innerHeight - $('html')[0].clientHeight));
content.push('HTML 화면 크기 (Scroll 제외, 개발자 도구 제외) : ' + $('html')[0].clientWidth + ' * ' + $('html')[0].clientHeight);
content.push('----------');
content.push('Body 영역 크기 : ' + $('body')[0].clientWidth + ' * ' + $('body')[0].clientHeight);
content.push('Body 영역 크기 (Scroll 제외) : ' + $('html')[0].scrollWidth + ' * ' + $('html')[0].scrollHeight + ' (' + $('html')[0].scrollLeft + ', ' + $('html')[0].scrollTop + ')');
content.push('Body 영역 크기 : ' + $('html')[0].offsetWidth + ' * ' + $('html')[0].offsetHeight + ' (' + $('html')[0].offsetLeft + ', ' + $('html')[0].offsetTop + ')');
content.push('Body 영역 크기 : ' + $('body')[0].offsetWidth + ' * ' + $('body')[0].offsetHeight + ' (' + $('body')[0].offsetLeft + ', ' + $('body')[0].offsetTop + ')');
content.push('Body 영역 크기 : ' + $('body')[0].scrollWidth + ' * ' + $('body')[0].scrollHeight + ' (' + $('body')[0].scrollLeft + ', ' + $('body')[0].scrollTop + ')');
content.push('----------');
//--- id가 contentListMap인 영역의 크기
let obj = $('#contentListMap')[0];
content.push('contentListMap : ' + obj.clientWidth + ' / ' + obj.clientHeight);
content.push('contentListMap offset : ' + obj.offsetWidth + ' / ' + obj.offsetHeight + ' (' + obj.offsetLeft + ', ' + obj.offsetTop + ')');
content.push('contentListMap scroll : ' + obj.scrollWidth + ' / ' + obj.scrollHeight + ' (' + obj.scrollLeft + ', ' + obj.scrollTop + ')');
content.push('Header 높이 : ' + obj.offsetTop);
let contentHeight = (window.innerHeight - obj.offsetTop - $('#layoutFooter')[0].clientHeight);
content.push('Content 영역 높이 : ' + contentHeight + ', 중간 offsetTop : ' + (contentHeight / 2));
content.push('Footer 높이 : ' + $('#layoutFooter')[0].clientHeight);
$('#contentMap').html('' + content.join('
') + '');
//--- 화면 배치와 scroll
$('body').css('overflow', 'visible');
$('#contentListMap').css('height', contentHeight / 2);
$('#contentList').css('height', contentHeight / 2);
if (contentHeight / 2 < $('#contentListEnd')[0].offsetTop) {
$('#contentList').css('overflow-y', 'scroll');
} else {
$('#contentList').css('overflow-y', 'hidden');
}
$('#contentMap').css('height', contentHeight / 2);
$('#contentMap').css('overflow', 'hidden');
$('#contentChart').css('height', contentHeight / 2 - 1);
$('#contentChart').css('overflow', 'hidden');
데이터 비교 화면 설계
분석 대상 데이터 정의
시계열 데이터
화면 상단
좌측 선택 (버튼) : 화면 중앙의 "좌측 선택"을 보였다 안보였다가함
장비 (선택목록)
달력 : 챠트에서 마지막 날 지정
그룹 (버튼)
틱 (900, 세로선 없음)
초(900, 분당 세로선), 분(900, 10분당 세로선), 시(900, 일당 세로선)
일(600, 월당 세로선), 주(300, 년당 세로선)
월(120, 년당 세로선), 년(30, 년당 세로선)
화면에 표시하는 갯수 / 그룹당 최대 갯수, 최대 갯수 증가 버튼
저장 (버튼) : CSV, Excel, 이미지
설정 (버튼)
챠트 속성(탭), 화면 설정(탭), 내보내기(탭)
화면 중앙 (챠트 표시)
좌측 선택
챠트 형태
장비 : 지사/장비별 표시할 데이터 종류 선택
지표 : 선택시 하단 챠트로 각 지표를 표시 한다.
챠트 공통
가로선 : 날자와 시간 표시
세로선
툴팁 : 커서가 위치한 날자와 시간의 데이터 상세
드래그앤드랍 : 확대
더블클릭 : 축소
항목 선택 후 더블클릭 : 상세 정보 표시
챠트 삭제 (버튼) : 선택시 해당 챠트를 삭제 한다.
오른쪽 마우스 : 컨텐트 메뉴를 표시 한다.
상단 챠트
하단 챠트
디폴트 챠트로는 알람 발생 건수를 막대 그래프로 표시 한다.
우측 버튼
각종 기능 버튼 배치
화면 하단
좌우 스크롤 : 좌로 이동, 스크롤, 우로 이동
자동 스크롤 : 좌로 자동 스크롤, 중지, 우로 자동 스크롤
표시 갯수 자동 스크롤 : 마지막날 고정
수치 조회창 (버튼) : 커서의 위치에 따른 툴팁을 좌측 상단에 항상 표시 (이동 가능)
축소/확대 (버튼) : 축소, 전체, 확대
선택 사항
색상, 레이블
테이블
챠트 : Line, Bar / Pie, Map
분석
Scatter (산점도) : 두개의 데이터를 비교
Gantt Chart : 장애가 발생한 시간부터 종료된 시간까지 표시
Chart Library
주요 지도 API
vWorld 지도 : http://www.vworld.kr/dev/v4dv_apiuse_s001.do
Naver 지도 : https://www.ncloud.com/product/applicationService/maps
TOAST 지도 : https://www.toast.com/kr/service/application-service/maps
Kakao 지도 : https://apis.map.kakao.com/
Google 지도 : https://cloud.google.com/maps-platform/?hl=ko
OpenLayers : https://openlayers.org/
지도 API 비교 참조 (http://www.bluestones.biz/cms/4_%EB%B9%84%EC%A6%88%EB%8B%88%EC%8A%A4/%EC%A7%80%EB%8F%84.md)
Table
DataTables : https://datatables.net/
Recine.js : http://okfnlabs.org/recline/
FooTable : http://fooplugins.github.io/FooTable/
Tabulator : http://tabulator.info/
Gauge
Gauge.js : http://bernii.github.io/gauge.js/
Google Charts: Gauge : https://developers.google.com/chart/interactive/docs/gallery/gauge
D3.js: Gauge : https://plotly.com/javascript/gauge-charts/
참고 문헌
Last modified, 2020.06.16 ~ 2020.06.16, version 0.02