화면 HTML 에 data-m-type="…" 으로 배치하고, 스크립트에서 $p.get('id') 로 인스턴스를 얻어 메서드를 호출합니다.
ButtonGroup
data-m-type="buttonGroup"
화면 표준 버튼 영역 — data-m-buttons 에 적은 버튼을 엔진이 정한 정렬·간격·모양으로 나란히 둔다. 폼(data-m-form)을 연결하면 CRUD 버튼(신규·수정·저장·취소·삭제)의 표시/숨김까지 엔진이 폼 상태로 관리한다. ★ 기획 의도: 버튼을 화면마다 따로 만들면 「조회 중엔 신규·수정·삭제, 수정·신규 중엔 저장·취소」 같은 표시/숨김 분기를 화면이 직접 짜야 하고, 경우가 늘수록 코드가 꼬인다 — 그 분기를 엔진 한 곳으로 모아 없앤 것이다. 연동 폼의 상태(R 조회·U 수정·C 신규)와 데이터 유무만 보고 버튼을 자동으로 보이고 숨기며, 누르면 상태전환·초기화·필수검사를 먼저 한 뒤 화면 함수를 부른다 — 그래서 화면은 버튼 display 를 만지지 않는다. 표시 규칙: 신규=R · 수정/삭제=R+데이터 있음 · 저장/취소=U·C · 그 밖의 라벨=항상. 폼 없이 쓰면 적은 버튼(닫기·새 창으로 열기·실행 등)이 항상 보이는 표준 버튼 줄이 된다 — 버튼 모양·간격을 화면에서 맞추지 않아도 된다. ★ 유형(data-m-preset): 프로젝트가 moca_config.js 의 buttonGroupPresets 에 버튼 그룹 유형(모양·표시 규칙·클릭 공통 처리)을 이름으로 정의하고 화면은 그 이름만 고른다 — 승인·반려 같은 프로젝트 업무 버튼도 화면에 분기 코드 없이 쓴다(속성 preset 참조). 유형을 안 고르고 폼을 연결하면 엔진 기본 유형 crud(아래 표시 규칙)이다. pop 상세 구조의 모바일 뷰에선 목록 위 신규 FAB(+, floatingButton 컴포넌트) 자동 생성
class 자동(bd_modal_btns)
속성
id
data-m-type
data-m-form
연동할 form 의 id (같은 frame 스코프)
data-m-buttons
"라벨[|화면함수],…" 버튼 정의 목록 — 쉼표로 버튼을 나누고, 라벨 뒤 |화면함수 는 그 버튼을 누르면 엔진 동작에 이어 부를 함수(없으면 엔진 동작만). 라벨이 신규·수정·저장·취소·삭제면 crud 유형(폼 연결 기본)에서 그 역할의 표시 규칙·공통 처리가 붙는다. 다른 유형은 그 유형의 visible·before 가 라벨로 정하고, 규칙 없는 라벨은 항상 보이며 화면 함수만 부른다(폼 없는 [저장]도 그냥 보인다). 필요한 버튼만 적는다(5개 고정 아님). 화면 함수는 (버튼요소, 폼, pCtx) 를 받는다.
상세 폼 CRUD data-m-buttons="신규|$p.fn_new,수정|$p.fn_edit,저장|$p.fn_save,취소,삭제|$p.fn_delete" · 폼 없이 팝업 닫기만 "닫기|$p.fn_close" · 새 창 "새 창으로 열기|$p.fn_openWin"
data-m-preset
버튼 그룹 유형 이름 — 프로젝트가 moca_config.js 의 buttonGroupPresets 에 정의한 것을 고른다(엔진 기본은 crud 하나). 생략하면 폼(data-m-form)이 있을 때 crud, 없으면 엔진 기본 모양·전부 표시. 유형 = { cls(그룹 class — 모양은 프로젝트 CSS .bd_modal_btns.{cls} button), state(function(pCtx) → 상태값), visible({라벨: function(pState, pCtx) → 보일지}), before({라벨: function(pCtx) → false 면 화면 함수를 부르지 않음}) } — 전부 선택: cls 만이면 디자인 공통화, state+visible 이면 표시/숨김 공통화. visible 은 state 가 있어야 동작한다. pCtx = { form(연결 폼·없으면 null), group, scope($p), hasData, state, label·button(before 에서) }. 화면은 버튼 display 를 만지지 않는다(다음 applyStatus 가 덮는다).
정의 buttonGroupPresets: { approve: { cls: 'btg_approve', state: function (pCtx) { return pCtx.form ? (pCtx.form.getRowJSON().APPR_STATUS || '') : ''; }, visible: { '승인': function (pState) { return pState === 'REQ'; }, '반려': function (pState) { return pState === 'REQ'; } }, before: { '반려': function (pCtx) { if (pCtx.form.getRowJSON().REJECT_REASON) return true; moca.$g.alert('반려 사유를 입력하세요.'); return false; } } }, action: { cls: 'btg_action' } } · 화면 <div data-m-type="buttonGroup" data-m-preset="approve" data-m-form="fom_detail" data-m-buttons="승인|$p.fn_approve,반려|$p.fn_reject"></div> · 프로젝트 CSS .bd_modal_btns.btg_approve button[data-label="반려"] { color: var(--c-danger); } — ★ 선택자는 .bd_modal_btns.{cls} 로 시작(.{cls} 만이면 테마 CSS 에 진다). 프로젝트의 유형 목록은 프로젝트 표준에 있다. moca-engine.md §16-6
무엇을 고르는 달력인가 — 값 자릿수와 시작 뷰가 여기서 파생된다. 미지정 시 yyyyMMdd(일자). 대소문자·구분자 무시
data-m-value
선택값(숫자문자열 — 타입 자릿수). 사용자가 고르거나 setValue 하면 이 속성도 함께 갱신된다
data-m-startym
초기 표시 기준 연월(yyyyMM) — 미지정 시 값이 가리키는 달, 값도 없으면 오늘의 달
data-m-header
"false" 면 내부 헤더(이전 · 제목 · 다음 · 오늘) 숨김 — 화면이 이동 UI 를 직접 만들 때
data-m-todaybutton
"false" 면 헤더의 오늘 버튼만 숨김(기본 표시)
data-m-weekendoff
"true" 면 토·일을 비영업일로 표시(사선 배경). setData 의 dayInfo.off 가 우선이라 "쉬는 토요일만 예외" 같은 지정이 가능하다
data-m-legend
"true" 면 달력 아래에 범례(오늘 · 선택 · 공휴일 · 비영업일)를 표시한다. 견본이 실제 칸과 같은 모양(원 테두리 / 채운 원 / 빗금 사각)이라 "이 빗금이 뭔지"를 화면 안에서 알 수 있다 — 공휴일·비영업일 표시를 쓰는 화면은 켜는 편이 좋다. 월·연 뷰에서는 자동으로 숨는다(그 격자엔 해당 표시가 없다)
data-m-datemin
선택가능 하한(yyyyMMdd) — 범위 밖 칸은 눌리지 않는다. 우선순위: 엔진 기본(19720101) < mconfig.calendarDateRange < 이 속성
data-m-datemax
선택가능 상한(yyyyMMdd) — 기본 20401231
data-m-readonly
"true" 면 선택 잠금(달 이동·둘러보기는 그대로). form 일괄 setReadOnly 대상
data-m-ref
form 연동 데이터 키(DB 컬럼명) — setRowJSON 으로 값이 들어오고 상태전환(R/U/C)에 함께 묶인다
속성값
이벤트
data-m-onselect
사용자가 값을 확정했을 때 호출: fn(comp, value, view). setValue()는 발화하지 않는다(초기 바인딩·취소 원복용)
data-m-onviewchange
표시 기준이 바뀔 때 호출: fn(comp, ym, view) — 이전/다음·오늘·setViewYm·뷰 이동. 공휴일 조회를 여기에 건다. 초기화 시엔 미발화(화면 함수가 아직 정의 전) — 초기 조회는 onpageload 에서 getViewYm() 으로 직접
메서드
getValue()
선택값(숫자문자열 — 타입 자릿수, 선택 없으면 '')
var ymd = $p.get('cal_regDt').getValue()
setValue(value)
선택값 설정 + 그 값이 보이는 달로 이동(이벤트 미발화). 자릿수 미달 값은 선택 해제로 취급
$p.get('cal_regDt').setValue('20260815')
clear()
선택 해제(이벤트 미발화)
$p.get('cal_regDt').clear()
setData({dayInfo})
업무 표시 데이터 — 넘긴 즉시 다시 그린다. dayInfo {yyyyMMdd:{holi,off,badge,class}} — holi=공휴일명(빨간 날짜 + 칸에 이름 표시) · off=비영업일 여부(true/false — 주말 자동판정보다 우선) · badge=칸 우측 위 표식 · class=그 칸에 덧붙일 클래스
선택가능 범위를 런타임에 지정 — 경계가 다른 값에서 오는 화면용(발주일을 고른 뒤 입고일 하한이 정해지는 식). 고정 범위면 속성(data-m-datemin/datemax)으로 충분하다. 빈값/null 을 주면 그 쪽 속성을 지운다 = 무제한이 아니라 아래 단계(mconfig → 엔진 기본값)로 되돌아간다. 이미 고른 값은 건드리지 않는다
data-m-itemset='[{"value":"DEV","label":"개발","checked":true},{"value":"DES","label":"디자인"}]' · 단일 체크(data-m-checktype="single") '[{"value":"Y","label":"위 내용에 동의합니다"}]'
data-m-pageid
페이지 id(렌더 시 input id 접두사)
data-m-disabled
비활성화 여부
메서드
getValue()
단일=boolean / 그룹=checked value 배열
var arr = $p.get('cbg_agree').getValue() // ['Y']
setValue(value)
단일=boolean / 그룹=배열·단일값
$p.get('cbg_agree').setValue(['Y','N'])
setReadOnly(bool)
전체 disabled 전환
$p.get('cbg_agree').setReadOnly(true)
redraw(itemsetStr)
itemset 교체 후 재렌더(그룹)
$p.get('cbg_agree').redraw(itemsetStr)
Ckeditor
data-m-type="ckeditor"
리치 텍스트 에디터(CKEditor 래퍼)
class —
속성
id
data-m-type
data-m-readonly
읽기전용 여부("true" 면 시작 시 잠금)
data-m-fill
남은 높이 채우기(fauto) 여부. 미지정이면 채운다. 내용만큼만 높이를 쓰려면 "false" 를 준다 — class 를 직접 써서 끄는 방법은 없다
툴바 프리셋 강제(미지정 시 폭별 — 좁은 창·MDI 분할 칸(isMobileView)은 Mobile, 아니면 Default). "View" = 보기 전용 — 툴바·하단 경로·크기 조절 없이 항상 읽기 전용. 받은 메일·게시글처럼 남이 쓴 HTML 을 화면 CSS 와 격리해(에디터 iframe) 보여 줄 때 쓴다(script 는 CKEditor 내용 필터가 걷어낸다)
붙을 데이터셋 id(넥사크로식). 데이터셋의 데이터가 바뀔 때마다 draw({list}) 로 다시 채워진다(삭제 표시 행 제외). 코드/이름 키는 data-m-cdkey/nmkey 로 맞춘다
data-m-codeopt
코드 옵션(전체/선택 등 기본 옵션 추가 설정)
data-m-displayformat
표시 형식 — 옵션 라벨 템플릿. [value]/[label] 토큰 치환(예: "[value] [label]" → "01 항목1", "[label]" → "항목1"). 미지정 시 라벨만 표시
data-m-cdkey
선택값 코드 키(기본 cd)
data-m-nmkey
선택값 표시명 키(기본 nm)
data-m-parentcomp
연동할 부모 컴포넌트 id. Selectbox·Radio·Combobox의 값이 바뀌면 이 Selectbox를 자동 필터링하고, chooseOption이 없으면 첫 실제 항목을 선택
data-m-parentkey
각 목록 항목에서 부모 코드가 들어 있는 키. data-m-parentcomp 사용 시 필수
data-m-readonly
읽기전용 여부("true")
data-m-disabled
비활성화 여부 — setReadOnly 가 라이브 반영
code
현재 선택 코드값
data-m-srcid
데이터 소스 식별자
data-m-ref
form 연동 데이터 키(DB 컬럼명) — setRowJSON/그리드 양방향 매핑
data-m-defaultvalue
기본값
이벤트
data-m-onchange
값 변경 시(외부 핸들러). 핸들러: fn()
data-m-inneronchange
값 변경 시(엔진 내부 처리 후 추가 핸들러)
메서드
getValue()
선택 코드 반환(readonly 렌더 포함 — data-m-code)
var cd = $p.get('cmb_use').getValue()
getLabel()
선택 표시 라벨 반환
var nm = $p.get('cmb_use').getLabel()
setValue(value)
코드로 선택 변경(null 이면 data-m-defaultvalue, readonly 렌더면 코드/라벨 속성+표시 갱신)
$p.get('cmb_use').setValue('N')
setReadOnly(bool)
잠금 전환(읽기 input 렌더)
$p.get('cmb_use').setReadOnly(true)
getList()
chooseOption을 제외한 원본 목록 배열 반환
var items = $p.get('cmb_use').getList()
draw(options)
전달한 옵션만 현재 상태에 병합해 다시 그림. list, chooseOption:{code,name}(name 을 비우면 data-m-label, 그것도 없으면 「- 선택 -」), data-m-cdkey, data-m-nmkey, data-m-parentkey, data-m-parentcomp 지원
도움말 모달을 띄운다(툴바 ? 버튼과 같은 동작). 화면이 data-m-help 로 준 설명 + 뷰어 조작법을 함께 보여준다
destroy()
컴포넌트 제거 전 Viewer 인스턴스 해제. 위젯 onwidgetdestroy 등에서 사용
FileUpload
data-m-type="fileupload"
파일 업로드·목록
class —
속성
id
data-m-label
첨부 영역 라벨(기본 "첨부파일")
data-m-uploadurl
업로드 팝업 화면 URL(이 화면만 다른 팝업을 쓸 때). 생략하면 프로젝트 설정 mconfig.fileUploadPopup, 그것도 없으면 현재 프로젝트의 ui/com/POP_FILEUPLOAD_LOCAL.html 로 유도한다 — 프로젝트 전체의 업로드 방식은 화면마다 적지 말고 moca_config.js 에서 정한다
data-m-scopeid
스코프(frame) id
data-m-selectquery
파일목록 조회 queryId(기본 selectTerpFileGrid) — 프로젝트별 파일 테이블 사용 시 오버라이드
data-m-insertquery
신규 파일 저장 queryId(기본 insertTerpFile)
data-m-updatequery
파일 설명 수정 queryId(기본 updateTerpFileDesc)
data-m-deletequery
파일 삭제 queryId(기본 없음 — ★선언한 화면만 save() 가 삭제선택(☑='D') 행을 삭제한다). 미선언이면 D행은 건너뛰고 console.warn — 자체 삭제 엔드포인트를 쓰는 화면(TPL021)이 기본 쿼리로 엉뚱한 테이블을 지우지 않게 하기 위한 규약. 파라미터는 FILE_IDX·CONTENT_ID
data-m-autoheight
첨부 개수에 따라 높이를 접고 펴기(기본 true). "false" 면 박스 형태를 유지하고 높이는 CSS/레이아웃이 정한다 — 목록이 항상 보여야 하는 화면용
data-m-delcheck
삭제선택(☑) 컬럼 사용 여부(기본 true — 그리드 특수컬럼 규약과 동일). "false" 면 ☑ 자체가 없어 삭제대상 행이 생기지 않는다 → 삭제를 아예 막는 화면은 deleteQuery 도 필요 없다
속성값
attrValues.autoHeight
true
기본 — 0개면 툴바만, 1개 이상이면 최대 2행까지 펼침
false
박스 고정 — 부모 칸을 채운다(레이아웃 칸/CSS 로 높이 지정)
attrValues.delCheck
true
기본 — ☑ 체크 후 [저장] 시 deleteQuery 로 삭제
false
☑ 컬럼 미생성 — 첨부 삭제를 제공하지 않는 화면(공개 데모 등)
이벤트
data-m-onuploadclick
[파일업로드] 클릭 시(팝업 열기 직전). 핸들러: fn(fileupload인스턴스). ★ false 를 반환하면 팝업을 열지 않는다 — 업로드를 막고 안내만 하는 화면용(공개 데모 등). 툴바 버튼과 openUploadPopup() API 양쪽에 모두 걸린다
파일 행 더블클릭 시(PC). 핸들러: fn(grd, rowIndex, colIndex, colId). 미지정이면 기본 = 해당 행 파일 다운로드. ★ 모바일엔 더블클릭이 없어 컴포넌트가 다운로드 아이콘 버튼 컬럼을 자동으로 넣고(대신 [파일크기] 컬럼은 접힘) 그 버튼이 이 핸들러를 같은 인자로 호출한다 — 동작을 바꿔도 PC·모바일이 함께 따라간다
화면 위에 떠 있는 액션 버튼(FAB) — 기본 우하단, 꾹 눌러 드래그 이동. buttonGroup 모바일 신규 FAB 의 실체
class 자동(moca_fab)
속성
id
data-m-type
data-m-label
(선택) 아이콘 옆 텍스트 라벨 — 지정 시 알약형(moca_fab_ext), 생략 시 원형. aria-label 로도 사용(라벨 생략 시 마크업에 직접 준 aria-label 은 보존된다)
data-m-icon
아이콘 3형태 — 내장 "plus"(기본, 색 자동추종) / 이미지 경로("/"·"." 포함 시 img — 엔진·프로젝트 아이콘 모두 경로를 그대로 적는다) / 그 외 문자열은 글리프 텍스트(이모지 등, 색 자동추종). img 형태는 파일 원색이라 data-m-color 미적용(색 추종이 필요하면 data-m-iconmode="mask")
(선택) 경로 아이콘 렌더 방식 — 기본 img(파일 원색). "mask" 면 CSS mask 로 currentColor 를 채워 색(테마·상태)을 자동 추종. 내장 plus·글리프 아이콘에는 무관
data-m-iconmode="mask"
data-m-bgcolor
(선택) 배경색 — CSS 색상값. 기본 var(--c-primary)(테마 자동 추종)
data-m-color
(선택) 아이콘·글자색 — CSS 색상값. 기본 var(--c-bg)
data-m-position
초기 위치 모서리 — 기본 rb(우하)
data-m-draggable
"false" 면 꾹눌러 드래그 이동 끔(기본 켜짐). 이동 위치는 화면이 살아있는 동안만 유지(재로드 시 원위치)
data-m-onclick
클릭 시 화면 함수 — fn(comp). 드래그로 이동한 직후의 클릭은 발화하지 않는다
data-m-onclick="$p.fn_new"
data-m-scopeid
스코프(frame) id
속성값
attrValues.iconmode
img
img 태그로 파일 원색 렌더(기본)
mask
CSS mask + currentColor — 색(테마·상태) 자동 추종
attrValues.position
rb
우하단(기본)
lb
좌하단
rt
우상단
lt
좌상단
메서드
show()
표시(인라인 숨김 해제)
$p.get('fab_new').show()
hide()
숨김
$p.get('fab_new').hide()
Dataset
data-m-type="dataset"
데이터셋 어댑터 — 이름으로 부르는 데이터 묶음. 데이터 구조(컬럼)를 선언하고 그리드·폼·콤보를 data-m-dataset 으로 붙이는 넥사크로식(그리드 컬럼 id 와 데이터셋 컬럼 id 가 같으면 매칭)과, 그리드를 가리키기만 하는 방식 둘 다 된다. 행 상태(C/U/D)·변경분 수집·행 이동·찾기·집계를 데이터셋 API 로 다룬다(이주 팀용, 신규 화면 표준은 직접 바인딩 — 철학 8)
class —
속성
id
data-m-type
data-m-grid
붙일 그리드 id — 붙이면 그 그리드의 데이터가 곧 이 데이터셋이다(사본 없음). 화면 로드 후 자동 연결. 그리드 쪽에서 data-m-dataset 으로 붙여도 같다
data-m-form
붙일 폼 id(쉼표로 여러 개). 그리드가 함께 붙어 있으면 form 의 data-m-refgrid 연동(§19)에 위임한다
data-m-columns
컬럼 정의 JSON 배열 — [{id, label, type:"number"|"string"|"date", default, required:"true"}]. 자식 div(data-m-col) 선언과 같은 뜻이며 자식 div 가 있으면 그것이 우선. 선언한 컬럼은 setData/addRow 때 기본값·타입이 맞춰지고 validate 의 필수검사 기준이 된다. 그리드 컬럼과는 id 가 같으면 매칭된다(표시 속성은 그리드 컬럼에 적는다)
data-m-scopeid
스코프(frame) id
attrs.colDiv
data-m-col
컬럼 id(필수). 자식 div 하나가 컬럼 하나. 붙은 그리드의 data-m-col 과 id 가 같으면 그 컬럼이 이 데이터셋 컬럼이다 — 그리드에만 있는 컬럼은 행의 그 키를 그대로 보여 주고, 데이터셋에만 있는 컬럼은 화면에 안 보이는 데이터로 실려 다닌다
data-m-coltype
컬럼 타입 — "number"(숫자로 맞춤) | "string" | "date"(yyyyMMdd 문자열 그대로). 생략하면 값을 손대지 않는다
data-m-default
빈 행(addRow/insertRow)이나 값이 빠진 행에 채울 기본값. 없으면 문자열은 "", number 는 null
"true" 면 validate() 가 빈 값을 잡는다(그리드 컬럼에 required 를 안 적어도)
이벤트
data-m-onrowposchanged
현재 행이 바뀔 때(그리드 선택·setRowPosition·선택해제). 핸들러: fn({dataset,row,index})
data-m-onvaluechanged
값이 바뀔 때(setValue·그리드 셀 편집·refgrid 폼 편집 — 모두 setCellData 를 지난다). 핸들러: fn({dataset,index,column,value})
data-m-oncolumnchanged
valuechanged 의 넥사크로 이름 — 같은 순간, 같은 내용으로 함께 불린다
data-m-onload
setData/clear/reset/applyChange 로 데이터가 세팅된 뒤. 핸들러: fn({dataset,count})
프로퍼티
rowposition
현재 행 번호(없으면 -1). 대입하면 행 이동 — getRowPosition/setRowPosition 의 넥사크로 이름
ds.rowposition = 2
rowcount
행 수(삭제 표시 D 행 포함) — getRowCount 의 넥사크로 이름
ROWTYPE_NORMAL
행 상태 코드 1 — getRowTypeCode 비교용
ROWTYPE_INSERT
행 상태 코드 2(신규)
ROWTYPE_UPDATE
행 상태 코드 4(수정)
ROWTYPE_DELETE
행 상태 코드 8(삭제)
메서드
setData(list)
데이터 세팅 — 선언 컬럼대로 기본값·타입을 맞춘 뒤, 그리드가 붙어 있으면 그리드가 그린다
$p.get('ds_emp').setData(res.list)
getData()
현재 데이터 배열(사본 아님, 삭제 표시 D 행 포함)
getRowCount()
행 수(D 행 포함)
getRow(index)
행 객체
getValue(index, colId)
셀 값. 행 번호를 빼고 getValue(colId) 로 부르면 0번 행(단건)
setValue(index, colId, value)
셀 값 변경 — 행 상태(U)와 valuechanged 통지까지 함께. 행 번호를 빼고 setValue(colId, value) 로 부르면 0번 행(단건)
setMap(obj)
단건 세팅 — 행 하나짜리 배열로 바꾼다(선언 컬럼대로 기본값·타입을 맞춘다). 붙은 폼이 채워진다. 종류 구분은 없다: 어느 데이터셋이든 0번 행이 단건이다
$p.get('ds_cond').setMap({ DEPT: 'DEV' })
getMap()
단건 객체 = 0번 행(사본 아님, 비어 있으면 선언 기본값 행을 만든다) — 조회조건 body 로 그대로 보낸다
tran.select({ body: $p.get('ds_cond').getMap() })
getColumn(index, colId)
getValue 의 넥사크로 이름
setColumn(index, colId, value)
setValue 의 넥사크로 이름
getOrgColumn(index, colId)
처음 받았을 때의 원본값(신규행은 undefined)
addRow([data])
신규행 추가(상태 C) — 맨 앞에. 선언 컬럼은 기본값으로 채워진다
insertRow(index[, data])
신규행을 그 자리에 끼운다(상태 C). 선언 컬럼은 기본값으로 채워진다
deleteRow(index)
삭제 — 신규행은 빼고, 서버에 있던 행은 D 로 표시
deleteAll()
전부 삭제 — 신규행은 빼고 나머지는 D 로 표시(한 번만 다시 그린다)
restoreRow(index)
그 행을 원본값으로 되돌린다
getRowType(index)
행 상태 'C'/'U'/'D'/''
getRowTypeCode(index)
행 상태를 넥사크로 숫자로 — 1 NORMAL · 2 INSERT · 4 UPDATE · 8 DELETE (ROWTYPE_* 와 비교)
getRowPosition()
현재 행 인덱스(없으면 -1)
setRowPosition(index)
현재 행 이동(그리드가 붙어 있으면 선택까지)
findRow(colId, value[, fromIndex])
컬럼 값이 같은 첫 행 번호(없으면 -1). 문자열로 비교한다
findRowExpr(expr[, fromIndex])
식이 참인 첫 행 번호(없으면 -1)
ds.findRowExpr("SAL >= 4000000")
getCaseCount([expr])
식이 참인 행 수 — 식이 없으면 D 행을 뺀 전체 행 수
getSum(colId[, expr])
컬럼 합계(숫자로 읽히는 값만)
getAvg(colId[, expr])
컬럼 평균
getMax(colId[, expr])
컬럼 최대값(없으면 null)
getMin(colId[, expr])
컬럼 최소값(없으면 null)
getModified()
변경분 전체(C/U/D) — 그리드 getModifiedJSON 과 같은 모양
getCreated()
신규행만
getUpdated()
수정행만
getDeleted()
삭제행만
applyChange()
저장 성공 뒤 변경분 확정 — D 행은 없애고 C/U 행은 상태를 비워 지금 값이 새 원본이 된다. 안 부르면 저장한 행이 다음 getModified() 에 또 나온다
validate()
필수값 검사 — 그리드 검사와 컬럼 선언의 required 를 모두 본다
clear()
전부 비운다
reset()
편집분을 버리고 원본 상태로
getColumnInfo(colIdOrIndex)
선언 컬럼 하나 {id,label,type,def,required,cls,extra}(사본, 없으면 null)
getColumnCount()
선언 컬럼 수(선언이 없으면 0)
bind(componentId)
그리드/폼/콤보를 붙인다(선언 속성 대신 코드로 붙일 때). 그리드는 하나만
unbind(componentId)
붙였던 것을 뗀다
on(eventName, fn)
코드로 이벤트 등록 — 'rowposchanged' | 'valuechanged' | 'columnchanged' | 'load'
off(eventName[, fn])
이벤트 해제
setEnableEvent(on)
통지 켜기/끄기 — 대량 setValue 때 잠깐 끄고 마지막에 켠다(넥사크로 set_enableevent)
getEnableEvent()
통지가 켜져 있는가
Transaction
data-m-type="transaction"
선언형 트랜잭션 — 통신할 것(url·queryId·요청 데이터 출처·응답 넣을 곳)을 HTML 에 선언해 두고 execute() 만 부른다. 실제 통신은 moca.$t.exe 에 위임하므로 CSRF·프로그레스·타임아웃은 그대로. 종전의 moca.$t.exe 직접 호출도 계속 된다
class —
속성
id
data-m-type
data-m-url
요청 URL. 생략하면 /common/select.do
data-m-queryid
조회 queryId(data.queryId). 응답은 moca.$t.exe 규약대로 {queryId: rows} 로 온다
data-m-insertqueryid
저장 — 신규(C) 행에 쓸 queryId(data.insertQueryId)
data-m-updatequeryid
저장 — 수정(U) 행에 쓸 queryId(data.updateQueryId)
data-m-deletequeryid
저장 — 삭제(D) 행에 쓸 queryId(data.deleteQueryId)
data-m-request
요청 데이터 출처 컴포넌트 id — 데이터셋(0번 행 또는 변경분)·폼(getRowJSON)·그리드(선택행 또는 getModifiedJSON)
data-m-send
요청 데이터 만드는 규칙 — "auto"(기본: 저장 쿼리가 있거나 url 에 save 가 있으면 modified, 아니면 map) | "map"(단건을 body 로, _system 제외) | "modified"(변경분 C/U/D 를 list 로 — 없으면 emptymsg 안내 후 보내지 않는다) | "all"(전체 행을 list 로)
data-m-response
응답을 넣을 컴포넌트 — "id" 또는 "id:응답키", 쉼표로 여러 개. 키 생략 시 queryId → list → list1 → data1 → 배열이 하나뿐이면 그것. 데이터셋은 setData(객체면 setMap), 그리드는 drawGrid, 폼은 setRowJSON
data-m-confirmmsg
실행 전 확인 문구(moca.$g.confirm). 취소하면 null 로 끝난다
data-m-successmsg
성공 알림 문구(moca.$g.alert). 생략하면 알림 없음
data-m-emptymsg
send=modified 인데 변경분이 없을 때 안내 문구(기본 "변경된 내용이 없습니다.")
data-m-applychange
"true" 면 성공 뒤 request 데이터셋의 applyChange() — 저장한 행이 다음 변경분에 또 나오지 않게
data-m-then
성공 뒤 이어서 실행할 트랜잭션 id(쉼표로 여러 개) — 저장 뒤 재조회 등
data-m-progress
"false" 면 프로그레스를 띄우지 않는다
data-m-footer
"false" 면 조회결과 푸터 표시를 하지 않는다
data-m-scopeid
스코프(frame) id
이벤트
data-m-onbefore
보내기 직전 — fn({transaction, data}). false 를 돌려주면 중단(검증·조건 확인)
data-m-onsuccess
응답을 넣은 뒤 — fn({transaction, res, data})
data-m-onerror
실패 — fn({transaction, error, data}). 그 뒤 execute 의 Promise 는 reject 된다
data-m-onafter
성공·실패 뒤 항상(then 트랜잭션까지 끝난 뒤) — fn({transaction, res|error, data})
메서드
execute([extra])
통신 실행 — Promise(응답). extra 는 조회조건에 덧붙일 객체(map) 또는 data 에 합칠 객체. 중단(변경분 없음·onbefore false·confirm 취소)은 null
await $p.get('tx_list').execute({ USE_YN: 'Y' })
getRequestData([extra])
execute 가 보낼 데이터를 미리 본다 — {queryId, body} 또는 {…QueryId, list}
on(eventName, fn)
코드로 이벤트 등록 — 'before' | 'success' | 'error' | 'after'
off(eventName[, fn])
이벤트 해제
Form
data-m-type="form"
폼/검색 테이블 래퍼 — 구조는 data-m-body(tbody) · data-m-row(tr) · data-m-cell(th|td) 로 적는다(컴포넌트가 아니라 data-m-type 을 쓰지 않는다)
class moca_table_form / moca_table_search / moca_table_view — data-m-variant 값에 따라 엔진이 자동 부여
속성
id
data-m-variant
★ 폼 변형 — "form"(상세 입력용) / "search"(조회조건용) / "view"(보기 전용 요약). 값에 따라 엔진이 moca_table_form · moca_table_search · moca_table_form+moca_table_view 클래스를 붙인다(값 목록은 attrValues.variant). 빠뜨리면 클래스가 하나도 안 붙어 th/td 스타일이 통째로 빠진다 — 에러도 경고도 없다. 단 data-m-refgrid 가 있는 폼은 엔진이 "form" 으로 추론해 되써 준다(그리드에 붙은 폼은 상세폼이다). 그래도 명시가 표준이고, 명시한 값이 언제나 이긴다. 화면이 class 로 직접 써도 동작한다(구 화면 호환)
폼 상태 — 'R'(읽기, 기본) / 'U'(수정) / 'C'(신규). setStatus/getStatus 로 접근
data-m-refgrid
참조 그리드 — 그리드 id 또는 스크립트 표현식(예: "$p.get('comTree').getScope().get('menuGrid')"). 지정 시 양방향 자동 연동: ① 그리드 행선택(moca:rowselect) 관찰 → setRowJSON(선택행) ② 폼 필드 수정(input/change) → 그리드 선택행 setCellData 실시간 반영(+원본비교 status 'U')
data-m-dataset
붙을 데이터셋 id(넥사크로식). 데이터셋에 그리드가 붙어 있으면 data-m-refgrid 를 심어 §19 연동에 위임하고, 없으면 현재 행(처음엔 0번 — 행이 없으면 선언 기본값 행 하나를 만든다)을 setRowJSON 으로 채우고 폼 편집을 그 행에 되돌린다(조회조건·단건)
속성값
attrValues.cell
th
라벨 칸 — 오른쪽 정렬 라벨. 필수값 메시지의 이름도 여기서 읽는다
td
값 칸 — 입력 컴포넌트를 담는다
attrValues.variant
form
상세 입력용 — 라벨 고정폭 우정렬 + 격자. 그리드와 data-m-refgrid 로 잇는 폼은 이것(refgrid 가 있으면 엔진이 이 값으로 추론)
search
조회조건용 — 카드 박스, 라벨·입력이 한 줄에 가로로, 좁아지면 세트 단위 줄바꿈(§87)
view
보기 전용 요약(이력·결과·상세 보기) — 값은 입력 상자가 아니라 글자. td 안에 output 컴포넌트(data-m-type="output" + data-m-ref="KEY") 하나만 두고 setRowJSON 으로 채운다(구 span data-m-ref 는 폐지 — page-lint 오류). 그리드에 붙은 폼(data-m-refgrid)이면 값이 그리드 컬럼 표시(쉼표·날짜)를 그대로 따른다. 라벨 열은 가장 긴 라벨 폭, 값은 길면 줄바꿈(잘리지 않음), 라벨·값 한 쌍뿐인 행은 값이 줄 끝까지 편다. 빈 값은 「—」. 읽기전용 input 상자로 요약을 보여 주지 않는다(한 줄에 잘리고 흐리다)
이벤트
data-m-oncellclick
행/셀 클릭 시(showRowSelection="true"). 핸들러: fn(event)
data-m-onfoldclick
접기/펼치기 후. 핸들러: fn(btnEl, formEl)
메서드
setRowJSON(rowData)
행 데이터 → data-m-ref 매핑 필드 일괄 세팅. 기간 달력(data-m-ref="시작키,종료키")은 두 키를 {from, to} 로 묶어 넣는다. 모든 필드는 컴포넌트라 setValue 로 채운다(보기 전용 값은 output 컴포넌트) — reset() 은 비운다. getRowJSON 은 output 을 모으지 않는다
다른 행 이동 시 편집유실 방지 confirm을 사용하는 Grid opt-in("true"). 단건은 현재 선택행 U/C를, editGuardTarget 지정 시 대상 상세 Grid 변경분을 감시
data-m-editguardtarget
1:N 화면에서 변경을 감시하고 확인 시 폐기할 상세 Grid id 또는 스크립트 표현식. 미지정이면 자기 Grid 선택행 U/C 감시. ★ 상세 Grid id 를 주면 디테일 잠금도 엔진이 한다 — 마스터 선택 행이 저장 전(status C)이거나 선택이 없으면 그 디테일의 [행추가]·[행삭제]·툴바 화면 버튼(저장 등)을 잠근다(disabled + 까닭 title). 저장 전 부모 키로 디테일을 insert 하면 FK 위반이기 때문이다. 관계는 이 속성 한 곳에만 적는다 — 디테일 쪽에는 아무것도 주지 않는다
디테일 잠금 안내(잠긴 버튼의 title) — 기본 「선택한 상위 항목을 먼저 저장하세요.」 마스터에 준다
data-m-editguardlockmsg="그룹을 먼저 저장하세요."
data-m-editguardmsg
편집가드 confirm 안내 메시지 커스텀(HTML 허용)
data-m-autoselectfirst
drawGrid 후 목록이 있으면 첫 행 자동선택("true") — PC 한정(모바일은 미선택). onRowSelected 도 유발
data-m-toolbarbtnpc
[PC] 툴바 버튼 일괄 지정(JSON) — 단일 경로. 값은 "true"/"false" 문자열. 키: detail(행 상세뷰. "true"=내장 상세뷰 — 선택 행의 전 컬럼을 라벨—값으로 펼친다. 기본 3단·버튼 3·2·1단 순, 모바일은 1단 고정. input/selectbox/combobox/radio/checkbox 셀타입은 상세뷰에서 실제 컴포넌트로 렌더되어 편집 가능하고 수정값은 setCellData 경로로 행에 반영(행상태 U·저장 대상 포함) — readonly·displayfunction 컬럼과 그 외 셀타입은 표시 전용. "dblclick"=내장 상세뷰 대신 화면의 data-m-ondblclick 함수를 호출 — 화면 자체 상세 UI 로 진입시킬 때. 미선택 시 선택 안내) / exup(엑셀업로드) / exdn(엑셀다운로드) / addrow(행추가) / delrow(행삭제 — 삭제선택(X) 컬럼이 있으면 버튼을 그리지 않는다(같은 기능). 편집 그리드 판정에는 그대로 쓰이므로 선언은 유지. 버튼을 쓰려면 data-m-delcheck="false") / delrowimd(행삭제 즉시 서버반영) / full(전체화면) / dblclick(더블클릭 동작) / colshowhide(컬럼 표시·숨김) / nextbtn(더보기) / fold(툴바 접기) / searchsize(검색창 크기)
[모바일] 툴바 버튼 일괄 지정(JSON) — 키는 toolbarBtnPc 와 동일. 단, detail 상세뷰는 모바일에서 폭이 좁아 1단 고정(3단 버튼 없음).
data-m-toolbarbtnmobile='{"fold":"true"}' · 편집 그리드 '{"addrow":"true","delrow":"true","fold":"true"}'
data-m-toolbarleft
툴바 좌측 영역에 추가할 버튼 정의(JSON 배열) — 항목 {type:"button",id,label,onclick}. ★ type 은 "button" 만 그린다(다른 값은 오류 없이 사라진다). onclick 은 함수 이름만(괄호 없이 — 엔진이 (this) 를 붙인다). 버튼 하나면 data-m-toolbarbtn1 이 표준이다
붙을 데이터셋 id(넥사크로식). 그 데이터셋이 이 그리드의 데이터를 가리키게 된다. 컬럼은 종전대로 이 그리드가 선언하고, data-m-col 이 데이터셋 컬럼 id 와 같으면 그 컬럼끼리 매칭된다. 데이터셋 하나에 그리드는 하나만
data-m-src
그리드 데이터 소스 식별자
data-m-onscrollend
스크롤이 끝에 닿았을 때 호출할 함수명(무한 스크롤)
data-m-renderingdiv
input 셀을 div 렌더 모드로("true") — 모바일 편집 UI 최적화
data-m-rowbgcolorfunction
행 배경색을 동적으로 반환하는 함수명(행별 조건부 색상)
data-m-usetree
트리 그리드 사용 여부("true"). celltype=tree 셀이 있으면 엔진이 자동 세팅
data-m-treetdid
트리 셀(td)의 id — 엔진이 자동 세팅
data-m-treelevelid
트리 레벨 값을 담는 row 필드 id — 엔진이 자동 세팅
data-m-depth1iconclass
트리 1depth 노드 아이콘 class
data-m-depth2iconclass
트리 2depth 노드 아이콘 class
data-m-depth3iconclass
트리 3depth 노드 아이콘 class
data-m-depth4iconclass
트리 4depth 노드 아이콘 class
data-m-depth5iconclass
트리 5depth 노드 아이콘 class
data-m-filterdistinctlimit
[엔진가드] 필터 distinct 임계치 — 고유값이 이 수를 넘는 컬럼은 집계를 중단하고 필터를 비활성화하여 키성(고유값 과다) 컬럼에 실수로 filter 를 줘도 브라우저가 멈추거나 죽지 않게 한다. 화면별로 grid 속성 data-m-filterdistinctlimit 로 조정 가능 (기본 1000).
data-m-subtotal
소계 그룹 기준 컬럼(td id). 지정 시 그룹값이 바뀌는 경계마다 소계행 자동 생성(라벨 "그룹값 소계"). 목록은 그룹 순 정렬 전제 — 다른 컬럼 정렬로 그룹이 흩어지면 소계는 자동 생략(합계는 유지). 콤마 다단 문법은 예약(v1 은 첫 컬럼만)
data-m-total
합계행 자동 생성 — data-m-calc 컬럼이 있으면 기본 "true"(=bottom, 맨 아래 고정). "top"=맨 위(thead 바로 아래) 고정, "false"=끔. 값 종류는 attrValues.total 참고. 합계행은 위치와 무관하게 스크롤에 영향받지 않고 항상 표시된다
data-m-subtotallabel
소계행 라벨(기본 "소계") — 그룹값 뒤에 붙는다(예: "수도권 소계")
data-m-totallabel
합계행 라벨(기본 "합계")
data-m-rownum
행번호(No) 컬럼 자동생성 — displayFunction moca.$g.rownum 표시전용 컬럼을 맨 앞에 추가
data-m-rowstatus
행상태(C/U/D) 컬럼 자동생성 — _system.status 표시 컬럼(columnkey "status") 추가. 기본 "auto": 편집 그리드(툴바 addrow/delrow · 편집 셀타입 · 폼 refgrid 대상)에만 생기고 조회 전용 목록에는 안 생긴다 — 화면이 판단할 필요 없음. "true"/"false" 명시가 우선
data-m-delcheck
삭제선택 컬럼 자동생성 — 체크='D'/해제=원상태 체크박스 + 헤더 전체선택(columnkey "DEL_CHK") 추가. 기본 "auto": 편집 그리드에만 생긴다(rowStatus 와 같은 판정). "true"/"false" 명시가 우선
data-m-type
id
class
attrs.colDiv
data-m-col
[단축 선언 마커·필수] 컬럼 id(DB 컬럼명 대문자) — td id·col columnkey 로 전개되고 th id 는 "H_"+id
data-m-width
컬럼 폭(예 "130px") — col style width 로 전개. 미지정 = auto(flex) 컬럼(여분 폭 흡수). 제목(+정렬·필터 버튼·필수 *)이 안 들어가면 엔진이 그 폭까지 늘린다(줄이지는 않는다 — 제목 길이에 맞춰 화면이 폭을 계산할 필요 없음)
data-m-label
헤더(th) 표시 텍스트 — 미지정 시 컬럼 id 표시
data-m-sortable
"true" 면 th 에 정렬 버튼 — th data-m-sortable 로 전개
data-m-filterable
"true" 면 th 에 필터 버튼 — filterableid 는 컬럼 id 자동(다르게 줄 때만 data-m-filterableid)
data-m-checkall
"true" 면 헤더에 전체선택 체크박스(§20) — th data-m-celltype="checkbox" 로 전개. 셀이 checkbox 인 컬럼에 준다
data-m-hide
"true" 면 컬럼 숨김(col 로 전개, 기기 무관 폭 0)
data-m-mobilehide
"true" 면 모바일에서만 숨김(col 로 전개)
data-m-celltype
셀 타입(td 전달) — 미지정 = input. input 셀은 readonly 미지정 시 "true"(조회 목록 기본) — 편집 컬럼만 data-m-readonly="false" 명시
data-m-excelindex
엑셀 다운로드 순서(td 전달) — 화면이 하나도 안 적으면 숨김 제외 컬럼에 선언 순서대로 자동 채번
data-m-datatype
컬럼 데이터 종류 — money | date. 이 속성 하나로 표시 함수와 정렬이 자동으로 붙는다: money → data-m-displayfunction="moca.$g.comma" + class tar(20140101 은 그대로, 1234000 → 1,234,000) / date → data-m-displayfunction="moca.$g.dateFormatter" + class tac(20140101 → 2014-01-01, 시각이 붙은 값도 날짜만 — 시각까지 보이려면 data-m-displayformat="yyyy-MM-dd HH:mm"). 화면이 displayfunction 이나 정렬 class(tal/tac/tar)를 직접 주면 그쪽이 우선. 값은 원본 그대로(모델 불변) — DB 형식은 묻지 않고 숫자 모양이면 된다. inputCalendar 셀에 date 를 주면 정렬만 붙는다(달력 셀이 자체 날짜 표시)
표시 함수 — 셀 값을 화면 표시용으로만 가공(모델은 원본 유지). 내장: moca.$g.comma · moca.$g.dateFormatter(날짜 — 형식은 컬럼 displayFormat) · moca.$g.phoneWithDashFormatter · moca.$g.percentFormatter · moca.$g.rownum(행번호). 입력제어(keyMask)와 독립. button 셀에서는 fn(값, grd, realIndex, colId) 의 결과가 행별 버튼 라벨이 된다(빈 값이면 btnLabel)
data-m-displayfunctionapply
"realtime"=keyup 마다 표시 포맷. 모델(getCellData)에는 항상 원본값 저장 — 표시함수에 역변환 companion fn.parse 필요(예: moca.$g.comma.parse), 없으면 입력값 그대로 저장
data-m-disabledfunction
비활성화 여부를 동적으로 반환하는 함수명
data-m-keymask
입력제어 마스크(편집 셀) — 키 차단/대소문자 강제만 담당. 값 종류는 Input 의 attrValues.keyMask 와 동일(onlyNumber/onlyMoney/onlyFloat/onlyPhone/upper/lower/enterSearchEvt). 표시 가공은 displayFunction 몫
data-m-maxlength
입력 최대 길이
data-m-calc
집계 대상 컬럼 표시(§49) — sum/count/avg/min/max. 값 종류는 attrValues.td.calc 참고. 컬럼마다 다른 연산을 섞어 쓸 수 있다(수량=sum, 단가=avg …). 하나라도 선언하면 합계행이 자동 생성(data-m-total 기본 true), 소계는 그리드 data-m-subtotal 로. 표시 포맷은 컬럼의 displayFunction 을 그대로 따른다. 빈 값은 어떤 연산에도 세지 않는다
data-m-colmerge
"true"면 이 컬럼에서 연속 같은 값 셀을 진짜 rowspan 으로 세로 병합(§49) — 드래그/복사해도 값이 한 번만 잡힌다. readonly + celltype input 컬럼만 대상(편집 셀 좌표와 충돌 방지). 목록이 이 컬럼 순으로 정렬돼 있을 때 의미가 있고, 소계행이 사이에 끼면 병합이 끊긴다(정상). 병합 셀 클릭은 병합 구간 첫 행을 선택한다
data-m-colmergealign
colmerge 병합 셀의 텍스트 세로 위치 — 기본 가운데(middle), "top" 이면 셀 위쪽에 붙인다
data-m-editormode
에디터 모드(편집 컴포넌트 종류)
data-m-addroweditable
행 추가(status=C) 시 편집 가능 여부("false"면 추가행에서도 잠금)
data-m-defaultvalue
새 행(행추가·addRow)의 이 칸 초기값 —
사용여부 "Y". 지정하지 않으면 **필수(data-m-required="true") 콤보 칸은 목록의 첫 항목**, 그 밖은 빈 값으로 시작한다. 값이 채워져 시작하므로 콤보에 「-선택-」 이 나오지 않는다(빈 채 저장돼 DB 에 빈 코드가 쌓이던 것) 예) <div data-m-col="USE_YN" data-m-celltype="selectbox" data-m-defaultvalue="Y" data-m-itemset=…>
data-m-align
셀 정렬(left/center/right)
style
셀 인라인 스타일
data-m-required
필수 입력 여부("true")
data-m-popupurl
팝업 호출 URL
data-m-popupdata
팝업에 전달할 파라미터(JSON 등)
data-m-callfunction
셀 클릭/이벤트 시 호출할 함수명
data-m-itemset
selectbox/combobox/code 셀의 아이템 목록(JSON 배열). 항목은 {code,codeNm} 또는 selectbox 와 같은 {cd,nm}(필드명을 안 적으면 엔진이 알아본다). ★ JSON 값은 작은따옴표 속성으로 감싼다(큰따옴표 속성에 넣으면 속성이 [{ 에서 끊겨 화면이 안 열린다)
itemset 항목의 코드(value) 필드명(기본 code — 항목에 code 가 없고 cd 가 있으면 cd)
data-m-nmfield
itemset 항목의 표시명 필드명(기본 codeNm — 위와 같이 cd 로 알아보면 nm)
data-m-parentcol
같은 행에서 이 Selectbox/Combobox 셀의 목록을 결정하는 부모 컬럼 id. 부모 변경 시 chooseOption 또는 첫 실제 항목으로 하위 단계를 재귀 초기화
data-m-parentkey
목록 항목에서 부모 컬럼 코드가 들어 있는 키. data-m-parentcol 사용 시 필수
data-m-onselectchanged
selectbox/combobox 셀의 변경 이벤트 핸들러 함수명
data-m-levelid
트리 레벨 값을 담는 row 필드 id
data-m-labelid
트리 노드 라벨 값을 담는 row 필드 id
data-m-treeid
트리 노드의 고유 id 를 담는 row 필드 id (미지정 시 "MENU_ID"). _renderGrid 가 이 값을 그리드 div 로 복사해 트리 구성에 쓴다.
data-m-truevalue
체크박스 셀의 체크(true) 저장값
data-m-falsevalue
체크박스 셀의 미체크(false) 저장값
data-m-btnlabel
버튼 셀의 라벨 텍스트
data-m-excelindex
엑셀 다운로드 시 컬럼 순서 인덱스
data-m-name
엑셀 다운로드용 컬럼명
data-m-exdnwithlabel
엑셀 다운로드 시 라벨 포함 여부
속성값
attrValues.td
attrValues.td.cellType
input
일반 입력창 타입(기본) — readonly 면 텍스트 표시, 편집이면 input 렌더
selectbox
콤보(선택) 타입(구 select 개명 2026-07-21, 컴포넌트 명칭 selectbox 로 통일) — data-m-itemset 또는 grd[컬럼id] 코드 목록으로 옵션 구성. 클릭 시 네이티브 select 드롭다운
combobox
검색 필터형 콤보 셀 — selectbox 와 데이터구조(data-m-itemset / grd[컬럼id]) 동일하되, 클릭 시 검색 input + 필터 목록을 연다(항목 많을 때 유용). 값 변경은 data-m-onselectchanged 콜백
inputPop
팝업 검색 셀(구 inputButton 개명) — input 은 표시 전용, 돋보기/Enter 가 data-m-callfunction(el, realRowIndex, colId) 호출. 화면이 $p.openPop 으로 팝업을 열고 callback 에서 setCellData 로 반영
inputCalendar
날짜 선택 셀 — 달력 버튼/직접입력 모두 지원. 일자범위는 폼과 같은 체인(엔진 기본 → mconfig.calendarDateRange → td data-m-datemin/max)으로 검증
button
버튼 타입 — data-m-btnlabel 라벨, data-m-callfunction 호출, data-m-disabledfunction 으로 행별 비활성
checkbox
체크박스 타입 — data-m-truevalue/falsevalue 로 도메인 값(Y/N 등) 매핑
radio
라디오 버튼 타입
tree
트리 노드 타입 — data-m-usetree="true" 그리드에서 data-m-levelid/labelid 와 함께 사용
attrValues.td.dataType
money
금액 — data-m-displayfunction="moca.$g.comma"(천단위 쉼표) + class tar(오른쪽 정렬). 수량·건수에도 쓴다
date
날짜 — data-m-displayfunction="moca.$g.dateFormatter"(20140101 → 2014-01-01, 자릿수로 형식 결정·시각이 붙으면 날짜만) + class tac(가운데 정렬). 다른 모양은 data-m-displayformat="yyyy.MM.dd" 처럼 준다
attrValues.td.calc
sum
합산 — 숫자 값 세로 합계
count
건수 — 비어있지 않은 값의 개수(텍스트 컬럼도 가능)
avg
평균 — 숫자 합÷숫자 건수, 소수 2자리 반올림. 합계행은 전체 데이터 기준(소계 평균들의 평균이 아님)
min
최소값 — 숫자는 숫자로, 그 외(날짜 문자열 등)는 문자열로 비교
max
최대값 — 비교 규칙은 min 과 동일
attrValues.total
true
맨 아래 고정(기본) — "bottom" 도 동일. 스크롤 중에도 뷰포트 하단에 항상 표시(sticky)
top
맨 위(thead 바로 아래) 고정 — 스크롤과 무관하게 항상 첫 행으로 표시
false
합계행 생성 안 함(소계만 필요할 때)
이벤트
data-m-onrowselected
행 선택 시. 핸들러: fn(gridEl, realRowIndex, tdObj, gridInstance). 마우스 클릭·setRowSelect()·키보드 ↑/↓(행을 한 번 클릭해 포커스를 얻은 뒤 — 화면에 그려진 순서로 이동, 셀 편집 중에는 입력 커서가 우선) 모두 같은 경로로 발화한다
data-m-onbeforeclick
셀/행 클릭 → 데이터 반영 "전". 핸들러: fn(gridEl, realRowIndex, colId) (false 또는 Promise 반환 가능 — 후속 처리 제어)
data-m-onbeforeaddrow
툴바 [행추가] 직전. 핸들러: fn(grid) — false 를 돌려주면 행을 추가하지 않는다. 마스터-디테일에서 마스터가 저장 전(신규)이면 디테일 행 추가를 막는 자리(안내는 핸들러가 한다). 화면이 직접 부르는 addRow() 는 거치지 않는다
data-m-onbeforeaddrow="$p.fn_beforeAddCode"
data-m-onafterclick
셀/행 클릭 → 데이터 반영 "후". 핸들러: fn(gridEl, realRowIndex, colId)
data-m-ondblclick
행 더블클릭 시. 핸들러: fn(gridEl, rowIndex, colIndex, colId)
data-m-onselectchanged
selectbox/combobox 셀 값 변경 시. 핸들러: fn(realRowIndex, colId, beforeCd, beforeNm, newValue, label)
data-m-onscrollend
스크롤이 끝에 닿았을 때(무한 스크롤). 핸들러: fn()
data-m-onpageclick
페이지 버튼 클릭 시. 핸들러: fn(pageNum) — paging 속성(JSON)의 "data-m-onpageclick" 키로 지정
메서드
drawGrid(list)
데이터 배열 렌더(0건 → moca:rowclear 발행)
$p.get('grd_main').drawGrid(res.list)
redrawGrid()
현재 list 재렌더(스크롤 위치 유지)
$p.get('grd_main').redrawGrid()
draw(list, response)
조회응답 렌더(페이징 totalCnt 연동)
$p.get('grd_main').draw(res.list, res)
setCellList(colId, list, options)
Selectbox/Combobox 셀 컬럼의 원본 목록 설정. options는 chooseOption:{code,name}, data-m-cdkey, data-m-nmkey 지원. chooseOption이 없으면 부모 변경 시 첫 실제 항목 선택
확인창 후 필터 전체 해제 + 원본목록 재드로잉 — 엔진이 생성하는 헤더 해제버튼(i) onclick 용
realtimeSearch(el)
실시간 검색
doSort(el)
정렬 실행
Input
data-m-type="input"
텍스트 입력
class moca_input
속성
id
data-m-type
class
선택 — 정체성 클래스 moca_input 은 엔진이 자동으로 붙이므로 적지 않아도 된다. 여기에는 프로젝트 유틸리티 클래스(tar·fl 등)만 적는다
data-m-value
입력 값
data-m-inputtype
내부 input 의 type — "password" 면 마스킹 입력(로그인 비밀번호 등). 그 외 값·미지정은 전부 text. 종류는 attrValues.inputType 참고
data-m-required
필수 입력 여부("true")
data-m-readonly
읽기전용 여부("true")
data-m-innerdisabled
내부 input 비활성화 여부("true")
data-m-innerstyle
내부 input 인라인 스타일
data-m-innerclass
내부 input class
style
컨테이너 인라인 스타일
data-m-keymask
입력제어 마스크 — "무엇을 입력할 수 있는가"만 제어(키 차단/대소문자 강제). 종류는 attrValues.keyMask 참고. 표시 가공(콤마 등)은 displayFunction 몫 — 서로 독립이라 병행 선언 가능
data-m-maxlength
입력 최대 길이
data-m-placeholder
placeholder 문구
data-m-mobilehide
모바일에서 숨김 여부
data-m-displayfunction
표시 함수 — 확정된 값을 "화면에 어떻게 보여줄까"만 가공(모델값은 원본 유지, getValue 는 raw). 내장: moca.$g.comma(천단위 콤마) · moca.$g.dateFormatter(날짜 20140101→2014-01-01) · moca.$g.phoneWithDashFormatter(전화 하이픈) · moca.$g.percentFormatter(% 부착). 화면 함수($p.fn_xxx)도 가능 — fn(value)→표시문자열. 입력제어(keyMask)와 독립
data-m-displayfunctionapply
"realtime"=keyup 마다 표시 포맷. 모델(getValue)에는 항상 원본값 저장 — 표시함수에 역변환 companion fn.parse 필요(예: moca.$g.comma.parse), 없으면 입력값 그대로 저장
data-m-ref
form 연동 데이터 키(DB 컬럼명) — setRowJSON/그리드 양방향 매핑
data-m-scopeid
스코프(frame) id
속성값
attrValues.inputType
text
일반 텍스트 입력(기본값 — 미지정과 동일)
password
비밀번호 입력 — 브라우저 마스킹(●●●) 표시. getValue/setValue 등 메서드 동작은 text 와 동일
attrValues.keyMask
onlyNumber
자연수만 — 숫자·키패드숫자만 허용. 콤마·마이너스·소수점·영문·한글·특수문자 차단
onlyMoney
금액 — 숫자·콤마(,)·마이너스(-) 허용. 영문·한글·특수문자 차단
onlyFloat
소수 — 숫자·소수점(.) 허용. 콤마·마이너스·영문·한글 차단
onlyPhone
전화번호 — 숫자·마이너스(-) 허용. 콤마·영문·한글·특수문자 차단
upper
강제 대문자 입력 — 소문자를 타이핑해도 대문자로 바뀌어 "입력"된다(붙여넣기 포함, 캐럿 유지)
lower
강제 소문자 입력 — 대문자를 타이핑해도 소문자로 바뀌어 "입력"된다(붙여넣기 포함, 캐럿 유지)
enterSearchEvt
Enter 시 같은 검색영역(.moca_table_search)의 조회버튼(.btn_search) 자동 클릭
무엇을 고르는 달력인가 — 값 자릿수·달력 팝업 모드·기본 표시형식이 여기서 파생된다. 미지정 시 yyyyMMdd(일자). 구분자·대소문자 무시("yyyyMMdd hh:mm:ss" = yyyyMMddHHmmss)
data-m-displayformat
날짜 표시 형식 — # 자리표시 마스크. 값 숫자를 # 에 순서대로 끼움(예: "####-##-##" → "2026-07-16"). 미지정 시 data-m-datetype 의 기본형식(yyyyMM → "####-##" 등)
data-m-defaultvalue
초기값
data-m-showradiooption
라디오 빠른선택 옵션 노출 여부
data-m-selecteritem
멀티 캘린더 빠른선택 항목 — 쉼표로 나눈 라벨(JSON 아님 — 엔진이 쉼표로 자른다).
data-m-selecteritem="오늘,3일전,6일전" · "당년,전년"
data-m-maxtermbymonth
최대 선택 기간(개월)
data-m-maxtermbyday
최대 선택 기간(일)
data-m-maxtermbyyear
최대 선택 기간(년)
data-m-datemin
선택가능 최소 일자(yyyymmdd) — 달력 팝업에서 범위 밖 일·월·연은 아예 눌리지 않고(이동·오늘 버튼도 갈 곳이 없으면 잠김), 직접입력은 확정 시 거부된다. 우선순위: 엔진 기본 19720101 < mconfig.calendarDateRange.min < 이 속성
data-m-datemax
선택가능 최대 일자(yyyymmdd) — 동작은 dateMin 과 같다. 우선순위: 엔진 기본 20401231 < mconfig.calendarDateRange.max < 이 속성
data-m-calendarid
내부 캘린더 식별자(엔진 부여)
속성값
attrValues.dateType
yyyy
연 선택 — 값 4자리. 팝업이 연 목록으로 열린다
yyyyMM
연월 선택 — 값 6자리. 팝업이 월 목록으로 열린다
yyyyMMdd
기본 — 일자 선택. 값 8자리, 팝업은 일자 격자
yyyyMMddHHmm
일시(분까지) — 값 12자리. 일자 격자 + 시·분 선택, [확인] 으로 확정
yyyyMMddHHmmss
일시(초까지) — 값 14자리. 일자 격자 + 시·분·초 선택, [확인] 으로 확정. "yyyyMMdd hh:mm:ss" 로 써도 같다
현재 값(숫자만) 반환 — 자릿수는 data-m-datetype 을 따른다(yyyyMMdd 기본 8자리). ★ 기간(inputMultiCalendar)은 {from, to} 객체
var dt = $p.get('ipc_cal1').getValue() / var t = $p.get('imc_schRegDate').getValue(); // {from:'20140101', to:'20161231'}
getFrom()
기간(멀티) 시작일(숫자만). 단일 달력이면 getValue() 와 같다
$p.get('imc_schRegDate').getFrom() // '20140101'
getTo()
기간(멀티) 종료일(숫자만). 단일 달력이면 getValue() 와 같다
$p.get('imc_schRegDate').getTo() // '20161231'
setValue(value)
값 설정 — data-m-datetype 자릿수로 맞추고(넘치면 자르고 모자라면 월·일 01·시각 00 채움) data-m-displayformat 을 적용해 표시. 기간(inputMultiCalendar)은 {from, to} 를 받는다(getValue 결과를 그대로 되넣을 수 있다 — "" 는 둘 다 비움)
컴포넌트 타입 — 'layout' 명시 선언(권장). 생략 시 data-m-layout 보유만으로도 layout 으로 인식(하위호환)
data-m-layout
레이아웃 방향 + 비율 지정. 문법: "{방향}{토큰:토큰[:토큰…]}" ── 방향(첫 글자) ── v = 세로(위/아래 스택, flex-direction:column) h = 가로(좌/우 분할, flex-direction:row) (구문법 fallback: 상하/세로/col/column/tb/vertical → 세로) ── 비율(방향문자 뒤) ── 자식(칸) 개수만큼 토큰을 ":" 로 나열. 생략 시 균등(1:1:…). · 숫자 : 비율(flex-grow). 남은 공간을 숫자 비율대로 나눠 가짐. 예 "3:7" (0 = 그 칸 접기 — 사이드 토글에 setRatio 와 함께 쓴다) · "숫자px": 고정 크기 칸. 주축(row=폭 / col=높이) 기준 고정. 예 "200px" · "auto" : 남은 공간 전부 채움(grow 1). px·fit 칸과 짝지어 "고정+나머지" 패턴. · "fit" : 내용 높이만큼만 hug(flex:0 0 auto). 헤더·검색영역처럼 컨텐츠만큼만.
[루트 전용] 고정 폭 기준(비율 분할의 기준 크기). 숫자만 주면 px. 지정 시 flex 해제(고정크기 모드). 넘치면 부모가 스크롤.
data-m-height
[루트 전용] 고정 높이 기준. 숫자만 주면 px. 지정 시 flex 해제.
data-m-layout-part
칸 위치 표기(예: "root", "2.1", "2.2.1"). 사람이 중첩 구조를 읽기 위한 마커. 단 "root" 는 layout.js 가 소비 — 그 레이아웃 우측 하단에 골격 미리보기 FAB 를 주입(_injectDebugFab).
data-m-mobileview
좁은 패널/모바일(≤768px 또는 .mdi_narrow)에서 이 칸을 전체화면 오버레이 팝업으로 전환("pop"). CSS(mobile.css)+mdi.js 가 소비.
data-m-mobileheight
모바일(≤768px) 세로스택에서 이 칸의 높이 고정. 숫자만 주면 px(예 "360"). h(가로) 레이아웃은 토큰이 폭이라 모바일 높이를 명시할 수 없어서 쓰는 마커 — PC 는 완전 무영향. layout.js 가 --m-mbh 변수로 넘기고 모바일 미디어쿼리(moca.css)가 소비.
그리드+차트 h5:5 화면에서 그리드 칸에 "360" (TPL017)
data-m-mobilehide
"true" 면 좁은 화면에서 이 칸을 통째로 숨긴다 — 옆 설명·보조 칸을 접고 본문에 공간을 몰아줄 때. PC 무영향. 엔진이 감싸는 래퍼 칸까지 함께 숨긴다(안쪽만 숨기면 래퍼가 비율을 계속 차지해 그 자리가 빈다)
속성값
attrValues.layout
v
방향: 세로(column) 예시) v5:5 vfit:auto
h
방향: 가로(row) 예시) h3:7 hfit:fit:auto
auto
남은 공간 전부 채움(grow 1) — px/fit 칸과 짝지어 씀
fit
내용 높이만큼만 hug(flex:0 0 auto) — 헤더/검색영역용
attrValues.mobileView
pop
좁은 화면에서 전체화면 오버레이 팝업으로 전환
메서드
setRatio(ratioStr)
레이아웃 비율·방향 동적 변경 — 방향 문자를 붙이면 방향까지 바뀌고("v3:7"=세로 3:7), 생략하면("3:7") 현재 방향을 유지한다. 토큰 개수는 칸 수와 맞춘다(한쪽을 0 으로 주면 그 칸이 접힌다 — 사이드 토글). 바뀐 스펙은 data-m-layout 속성·골격 미리보기 라벨에도 반영된다.
표시 형식 — 옵션 라벨 템플릿. [value]/[label] 토큰 치환(예: "[value] [label]" → "01 항목1", "[label]" → "항목1"). 미지정 시 라벨만 표시
data-m-readonly
읽기전용 여부("true")
data-m-casesensitive
검색 시 대소문자 구분 여부. ★ 기본은 "false"(구분하지 않음) — 사용자는 코드를 소문자로 치는데(tpl024) 목록은 대문자(TPL024)라, 구분하면 있는 항목이 안 나오고 에러도 없어 없는 것으로 오해하게 된다. 코드 체계상 대소문자가 서로 다른 값인 화면에서만 "true"
data-m-casesensitive="true"
data-m-cdkey
선택값 코드 키(기본 cd)
data-m-nmkey
선택값 표시명 키(기본 nm)
data-m-parentcomp
연동할 부모 컴포넌트 id. Selectbox·Radio·Combobox의 값이 바뀌면 이 Combobox를 자동 필터링하고 첫 실제 항목을 선택
data-m-parentkey
각 목록 항목에서 부모 코드가 들어 있는 키. data-m-parentcomp 사용 시 필수
data-m-value
현재 선택 코드값
data-m-text
현재 선택 표시 텍스트
data-m-ref
form 연동 데이터 키(DB 컬럼명)
data-m-scopeid
스코프(frame) id
이벤트
data-m-inneronchange
값 변경 시(엔진 내부 처리 후 추가 핸들러)
메서드
getValue()
선택 코드 반환
var cd = $p.get('scb_1').getValue()
getLabel()
선택 표시 텍스트 반환
var nm = $p.get('scb_1').getLabel()
getList()
부모 필터 결과를 제외한 원본 목록의 복사본 반환
var list = $p.get('scb_1').getList()
setValue(value)
선택 코드 변경
$p.get('scb_1').setValue('2')
setReadOnly(bool)
잠금 전환
$p.get('scb_1').setReadOnly(true)
draw(options)
전달한 옵션만 현재 상태에 병합해 다시 그림. list, data-m-cdkey, data-m-nmkey, data-m-parentkey, data-m-parentcomp 지원. Combobox에 chooseOption을 전달하면 TypeError
setList(items)
기존 호환 API. draw({list:items})로 목록을 교체하고 다시 그림
setCdfield(fieldName)
기존 호환 API. data-m-cdkey를 변경하고 다시 그림
$p.get('scb_1').setCdfield('code')
setNmfield(fieldName)
기존 호환 API. data-m-nmkey를 변경하고 다시 그림
$p.get('scb_1').setNmfield('codeNm')
ScheduleCalendar
data-m-type="scheduleCalendar"
월간 일정 캘린더 — 스와이프·일정 표시(setData). 높이는 내용만큼 자란다(넘치면 문서 스크롤) — 남은 높이까지 채우려면 루트 레이아웃에 class="moca_layout_fill"
class 자동(moca_schcal) + 채우려면 루트 레이아웃에 moca_layout_fill
속성
id
data-m-type
data-m-startym
초기 표시 월(yyyyMM, 기본 오늘의 월)
data-m-header
"false" 면 내부 헤더(이전 아이콘 · 연월 · 다음 아이콘 · 오늘 아이콘) 숨김 — 화면이 이동 UI 를 직접 만들 때
data-m-dayrenderer
일 칸 추가 HTML 렌더러 함수경로 — fn(day) 가 반환한 HTML 이 날짜 배지 아래 삽입된다. day={ymd,dd,dow,inMonth,today}
data-m-todayflag
"true" 면 오늘 칸 위로 펄럭이는 TODAY 깃발 표시 — 셀 경계를 넘어 위쪽에 꽂힌 형태(첫 주 칸은 위 공간이 없어 셀 안쪽에 세운다). 당월 칸에만 달리고(이웃 달 슬라이드의 흐린 칸 제외), 클릭은 아래 셀이 받는다. 모션 최소화 설정에서는 흔들림만 멈춘다
data-m-titleedit
"true" 면 헤더의 연월을 입력칸으로 바꾼다 — 사용자가 직접 고쳐 포커스아웃(또는 Enter)하면 그 달로 이동한다(setYm 경유라 onmonthchange 발화). 입력은 구분자 무관 5~6자리 숫자로 읽는다("202608"·"2026.8"·"2026-08" 모두 가능), 못 읽거나 범위(연 1900~2999·월 1~12) 밖이면 현재 달로 되돌리고 아무 일도 하지 않는다. Esc 는 되돌리기. 평소 모양은 h2 제목과 같고 hover/focus 에서만 입력칸으로 드러난다(header="false" 면 헤더가 없어 입력칸도 없다)
data-m-menubutton
"true" 면 헤더 맨 앞(이전 달 버튼 왼쪽)에 햄버거 버튼을 둔다 — 화면이 옵션·메뉴 패널을 여는 진입점. 클릭은 data-m-onmenuclick 으로 받는다(header="false" 면 헤더가 없어 버튼도 없다)
data-m-barstyle
일정 바 모양 — "fill"(기본: 색면 칩, bg/fg 로 채움) 또는 "line"(채움 없이 왼쪽 세로 색 바 + 잉크색 제목). line 은 좁은 칸에서 잉크를 줄이고 어떤 달력 색에서도 글자 대비를 보장한다 — 바 색은 아이템의 line > mark > fg, 연속일정도 날마다 [바][제목] 을 반복하고, 오늘은 색면 대신 원형 배지, 이모지(ico)는 작은 원, 세로 칸 경계선은 지운다(가로 주 경계선만)
data-m-outsidemove
"true" 면 당월 밖 흐린 칸(전월 말·익월 초)을 눌렀을 때 그 달로 이동한다(setYm 경유라 onmonthchange 발화, ondayclick 은 부르지 않는다). 기본은 종전대로 ondayclick 만
data-m-bartint
"true" 면 barstyle="line" 의 바에 바에 색면을 깐다 — 세로 바만으로는 달력(채널)이 한눈에 안 갈린다는 취향용. 아이템에 bg 가 있으면(transparent 제외) 그 bg/fg 색면 그대로(AS-IS 칩 모양, 세로 바는 fg 색), 없으면 바 색(line > mark > fg)의 색상을 빌린 옅은 틴트(글자는 본문색). 완료 일정은 배경 없음, 연속일정은 한 띠로 이어진다. 런타임 토글은 setBarTint(on)(순수 CSS 라 재렌더 없음). fill 모드에서는 무시. 기본 false
속성값
이벤트
data-m-onmonthchange
표시 월 변경 시(스와이프/버튼/오늘/setYm) 호출: fn(comp, ym). 초기화 시엔 미발화 — 초기 조회는 화면 onpageload 에서 getYm() 으로 직접
data-m-ondayclick
일 칸 클릭 시 호출: fn(comp, day) — day={ymd,dd,dow,inMonth,today}. 일정 바를 눌렀을 때는 onitemclick 이 선언돼 있으면 그쪽이 대신 불린다
data-m-onitemclick
일정 바 클릭 시 호출: fn(comp, item, day) — item 은 getDayItems 항목과 같은 모양(원본 행은 item.data), day 는 ondayclick 과 같은 모양. 어느 일정을 눌렀는지는 바 마크업을 소유한 컴포넌트만 알 수 있어 이 이벤트로 넘긴다(화면이 DOM 에 직접 리스너를 걸지 않게). 선언하지 않으면 바를 눌러도 종전대로 ondayclick 만 불린다
목록을 거치지 않고 상세를 바로 열 때 $p.openPop({url:'…/POP_SCHVIEW.html', data:{row:item.data}})
data-m-onmenuclick
헤더 메뉴(햄버거) 버튼 클릭 시 호출: fn(comp) — data-m-menubutton="true" 와 함께 쓴다
메서드
setData({schedules, dayInfo, hideOutside})
일정 표시 표준 API — 연속일정 일자 전개·정렬(완료 뒤/연속 우선)·바 마크업(미완료 시작·단일·종료 마커/이모지/제목, 완료는 취소선+마커·아이콘 숨김, 시간은 표시하지 않음)·날짜영역 메타(공휴일/날씨/뱃지) 렌더와 refresh 까지 컴포넌트가 수행. schedules 아이템 {start(yyyyMMdd 필수), end, title, ico, done, crucial, span(생략 시 end>start), bg, fg, mark, line(barstyle=line 의 세로 바 색 — 없으면 mark > fg), emph(true 면 채우기 꺼진 line 모드에서 제목 글자도 바 색 — 바 하나로는 구분이 안 되는 「진한 배경 + 밝은 글자」 색면용), time(HHmm — 시작시간 정렬키), endTime(getDayItems 호출측 상세용), seq(동순위 최후 정렬키)} · dayInfo {yyyyMMdd:{holi,wthr,badges[],sub}} — sub 는 날짜 숫자 옆 보조 라벨(음력 8.15·주차 W34 등 그 날의 다른 이름), anniv 는 기념일명(쉬는 날 아님 — 날짜색 그대로 두고 일정 줄 맨 아래에 회색 한 줄, 여러 개면 「 · 」로 이어 넘긴다) · hideOutside(true 면 표시 월 밖 칸 — 전월 말·익월 초 — 에는 일정·메타를 그리지 않고 날짜만 남긴다)
그 날(yyyyMMdd)의 일정 목록을 화면 순서 그대로 반환 — setData 로 이미 인덱싱해 둔 것이라 서버 재조회가 필요 없다. 각 항목 = setData 아이템 사본 + pos('one'|'s'|'m'|'e' — 그 날이 단일/시작/중간/종료 중 무엇인지) + ymd. 아이템에 data(원본 행)를 담아 넘겼다면 그대로 실려 온다
line 모드 바 배경 틴트 켜기/끄기(data-m-bartint 의 런타임 판) — 사용자 보기옵션에 연결해 취향대로 색면을 넣고 뺀다. 순수 CSS 토글이라 setData·refresh 없이 즉시 반영, fill 모드에서는 무시
$p.get('scc_plan').setBarTint($p.opt['일정 색 채우기'] === 'Y')
getBarTint()
현재 배경 틴트 상태(true/false)
Tab
data-m-type="tab"
탭 컨테이너
class moca_tab
속성
id
attrs.btn
data-m-target
활성화할 패널의 id(=탭 식별자 tabId)
data-m-src
패널에 frame.load 로 로드할 화면 src
data-m-closable
탭에 닫기(✕) 표시("true") — 클릭 시 removeTab
data-m-disabled
탭 비활성화("true") — 클릭·selectTab 으로 전환 불가(ontabclick 은 발화). 런타임 변경은 setTabDisabled
이벤트
data-m-ontabclick
탭 헤더(버튼) 클릭 시 — 선택 확정 전이며 비활성(disabled) 탭에서도 발화. 핸들러: fn(comp, index, tabId), false 반환 시 전환 취소(veto). JS 로 붙일 때는 comp.onTabClick = fn(index, tabId)
data-m-ontabchange
탭이 활성화될 때(클릭·selectTab·addTab 등 코드 선택 포함). 핸들러: fn(comp, index, tabId) — JS 로 붙일 때는 comp.onTabChange = fn(index, tabId). 탭에 담긴 화면 쪽 라이프사이클은 $p.onactivate/$p.ondeactivate(scope 훅) 참조
메서드
selectTab(indexOrId)
탭 활성화(대상 패널에 data-m-src 화면 로드). 비활성(disabled) 탭은 거부
$p.get('tab_main').selectTab(0)
addTab(option)
탭 추가(버튼+패널 생성) — option {id, text, src, param, closable, index, select(기본 true), disabled}. 같은 id 가 있으면 활성화만. 반환 tabId
var i = $p.get('tab_main').getTabIndex('tabDetail')
getTabCount()
탭 개수 반환
var n = $p.get('tab_main').getTabCount()
getTabIds()
전체 탭 id 배열(표시 순서) 반환
var ids = $p.get('tab_main').getTabIds()
getTabTitle([indexOrId])
탭 제목 반환(생략 시 선택 탭)
var t = $p.get('tab_main').getTabTitle(0)
setTabTitle(indexOrId, title)
탭 제목 변경
$p.get('tab_main').setTabTitle(0, '목록(12)')
setTabDisabled(indexOrId, disabled)
탭 비활성화/해제 — 어느 탭인지(인덱스 또는 tabId)와 잠글지 여부(true/false)를 둘 다 지정한다(생략 불가, 생략하면 콘솔 경고 후 무시). 비활성 탭은 클릭·selectTab 으로 전환되지 않지만 ontabclick 은 발화하므로 "왜 안 되는지"를 안내할 수 있다. 현재 선택된 탭을 비활성화해도 선택은 유지되고 이후 재선택만 막힌다
날짜 하이픈(moca.$g.dateFormatter) — 시각이 붙어 와도 날짜만. data-m-displayformat 으로 모양 지정
메서드
setValue(value)
값 설정 — 원본을 두고 표시 글자(쉼표·날짜 등)로 보인다. 폼 setRowJSON 이 부른다
$p.get('out_amt').setValue(17340) // 17,340
getValue()
원본 값(표시 가공 전)
$p.get('out_amt').getValue() // 17340
setReadOnly(bool)
보기 전용이라 동작 없음 — 폼 일괄 잠금에 끼기 위한 자리
Treeview
data-m-type="treeview"
트리뷰
class 자동(moca_treeview)
속성
id
data-m-label
트리 맨 위 제목 헤더(폼·그리드와 같은 .moca_grid_toolbar). 이 속성이나 toolbarFold 가 있으면 트리 자체가 카드(테두리)가 되고 스크롤은 안쪽이 맡는다 — 화면이 lay_bd_detail·bd_panel_header 로 감쌀 필요가 없다(그 헤더는 모바일에서 제목이 숨는다). 레이아웃 칸으로 바로 둔다
"true" 면 트리 위에 전체펼침·전체접기 버튼 + 건수(전체 N · 펼침 M) 툴바를 컴포넌트가 직접 붙인다(기본 없음). 화면이 버튼을 만들고 expandAll/collapseAll 을 연결하고 건수를 세던 코드가 필요 없다 — 건수는 렌더될 때마다 스스로 갱신한다. 아이콘은 트리 노드의 +/− 와 같은 모양이라 "저 토글을 전부 누른 것"으로 읽힌다. 이때 스크롤은 루트가 아니라 안쪽 .mvt_scroll 이 맡는다(툴바가 함께 스크롤되지 않게)
행번호 칸 고정폭(px, 기본 34). 자릿수가 넘치면 칸을 넓히지 않고 글자를 가로로 눌러 넣는다(최대 50% — 그리드 행번호와 같은 방식). 칸을 자릿수만큼 넓히면 1만 행에서 본문이 밀려 트리 들여쓰기가 흔들린다
data-m-rowno
행번호 표시 — 기본 true(그리드와 같다). "false" 면 숨긴다. 번호는 보이는 순서(펼친 목록 기준)라 접고 펴면 다시 매겨진다. 가상 렌더는 스크롤해도 화면이 비슷해 보여 "지금 어디쯤인지·조금 움직였는지"를 번호로 확인한다. 맨 왼쪽에 고정(sticky)되어 가로 스크롤에도 남는다
data-m-onselect
노드 선택 시 호출할 화면함수명 — fn(node, comp). setOnSelect 와 병행 가능
data-m-label
트리 맨 위 제목 헤더(폼·그리드와 같은 .moca_grid_toolbar). 이 속성이나 toolbarFold 가 있으면 트리 자체가 카드(테두리)가 되므로 화면이 lay_bd_detail·bd_panel_header 로 감쌀 필요가 없다 — 그 헤더는 모바일에서 제목이 숨는다. 레이아웃 칸으로 바로 둔다
"true" 면 제목 헤더 우측에 접기 버튼 — 접으면 헤더만 남고 툴바·트리가 숨는다. 트리가 레이아웃 칸이면 칸이 내용높이(헤더)로 줄어 형제 칸이 그 공간을 가져간다(그리드 접기와 같은 규약, 모바일 data-m-mobileheight 칸도 헤더 높이로)
data-m-onfoldclick
접기/펼치기 후 호출할 화면함수명 — fn(btn, el). 그리드·폼과 같은 규약
attrs.row
data-node-id
트리 행(.mvt_row)에 부여되는 노드 식별자(node.id)
속성값
attrValues.defaultExpand
메서드
setData(nodes)
노드 배열({id,text,children}) 세팅 후 렌더
$p.get('vtr_cat').setData(res.list)
getData()
현재 노드 데이터 반환
var nodes = $p.get('vtr_cat').getData()
setOnSelect(fn)
노드 선택 콜백 등록 — fn(node, comp)
$p.get('vtr_cat').setOnSelect(function(n){ … })
getSelectedNode()
선택된 노드 객체 반환(없으면 null)
selectById(id)
특정 노드 선택 — 조상 자동 펼침 + 화면 안으로 스크롤. 콜백은 발화하지 않는다
scrollToId(id)
그 노드가 보이도록 스크롤(이미 보이면 그대로)
find(keyword[, option])
찾기 — 일치 노드 목록을 만들고 첫 일치로 이동·선택한 뒤 일치 건수를 반환한다. 접혀서 안 보이는 노드도 찾아 조상을 펼친다. option {field:'text'(기본) 또는 data 필드명, filter:fn(node)→bool, caseSensitive:false}. 콜백(onselect)은 발화하지 않는다(selectById 와 같은 규약). textviewer 와 같은 이름·계약이다
확인/취소 레이어. 3번째 인자=취소 콜백, 4번째=옵션 — {radios:[…]} 선택목록 또는 {input:{value,placeholder,maxlength,type}} 한 줄 입력칸(값 입력 프롬프트 — 이름 바꾸기 등). 확인 콜백 인자로 선택값/입력값 전달, Enter=확인
빈값 판정 — null/undefined 또는 trim 결과 '' 이면 true (grid/form validate() 공통 코어)
requiredFail(label, focusCb)
"{label}은(는) 필수입력항목입니다." 알림 + 확인 시 focusCb(포커스 이동) 실행 후 false 반환
getScope(node)
노드가 속한 frame 의 스코프 객체 반환(엘리먼트.getScope() 와 동일)
getFrame(scopeObj)
스코프 객체 → 그 frame 엘리먼트
getParentFrame(frameEl)
frame 엘리먼트 → 부모 frame 엘리먼트
resolveFn(expr)
함수명 문자열(점경로 "moca.$g.comma", "m$3.fn")을 함수 참조로 해석 — 함수 아니면 null
date.*
날짜 유틸 네임스페이스 — 함수 목록은 아래 $g.date 절에 전부 있다(구현 js/date.js, 화면 스크립트에 $g.date 가 보이면 자동 로드). 값은 어디서나 숫자 문자열(yyyyMMdd · yyyyMM · yyyyMMddHHmmss)
moca.$g.date.getToday()
getUserInfo()
로그인 사용자 정보(U_ID, U_NAME …) — sessionStorage loginInfo 를 파싱해 반환(미로그인 시 null). 스토리지가 막힌 브라우저(iOS 프라이빗·쿠키 전체 차단·일부 인앱)에서는 접근 자체가 SecurityError 를 던지므로 내부에서 가드해 null 을 반환한다 — 화면은 sessionStorage 를 직접 읽지 말고 이 함수를 쓸 것
getDevice()
'pc' | 'mobile' — 기기 판별(screen.width 1280px 미만이면 mobile). 창 리사이즈에 안 반응하므로 반응형 판정엔 isMobileView 를 쓸 것
isMobileView(el)
반응형(폭 기반 UI 분기) 판정 단일 소스(moca-rules.md §7 반응형) — 뷰포트 ≤768px(@media 와 동일) 또는 el 이 MDI 분할 좁은 패널(.mdi_narrow) 안이면 true. 폭에 따라 다르게 렌더/동작하는 코드는 반드시 이 함수로 판정. 예외: PC 에서 $p.openWin 으로 연 브라우저 창 팝업(html.moca_pcwin)은 창이 좁아도 false — 그 문서는 mobile.css 도 꺼진다(§0-9-1)
chime([kind])
알림음 — 오래 걸리는 작업이 끝났을 때 다른 탭에 있는 사람을 부른다. 음원 파일 없이 Web Audio 로 짧은 두 음을 합성한다. kind: 'ok'(기본, 올라가는 두 음) | 'fail'(내려가는 낮은 두 음). 사람이 그 페이지를 한 번도 누르지 않았으면 브라우저가 소리를 막으므로 조용히 넘어간다(오류 없음) — 버튼으로 시작한 작업의 끝에서 부르면 탭이 뒤에 있어도 울린다
moca.$g.chime(ok ? 'ok' : 'fail')
code(config, callback, scope)
공통 코드 바인더 코어 — 화면에서는 $p.code() 로 호출한다(스코프 자동 바인딩)
listToMap(list, option[, filterableId])
배열 → 맵. option.metaInfo:{codeCd,codeNm} 로 code→명칭 맵 생성(기본 code/codeNm 필드), option 없으면 filterableId 값 기준 맵
comma(n)
천단위 콤마. 역변환 companion comma.parse(s)(콤마만 제거) 보유 — displayfunctionapply="realtime" 의 원본값 복원용
phoneWithDashFormatter(v)
전화번호 대시 포맷
percentFormatter(v)
퍼센트 포맷
dateFormatter(v)
날짜 표시 — 숫자 날짜에 구분자를 붙인다(모델은 원본 유지). 형식은 그리드 컬럼의 data-m-displayformat(토큰 yyyy·MM·dd·HH·mm·ss)이 있으면 그것, 없으면 자릿수로 — 4:yyyy · 6:yyyy-MM · 8:yyyy-MM-dd · 12:yyyy-MM-dd HH:mm · 14:yyyy-MM-dd HH:mm:ss. 숫자만 뽑아 읽어 DB 일시("2021-12-14T01:09:01")도 받고, 14자리를 넘으면(밀리초) 앞 14자리만 읽는다. 컬럼이 data-m-datatype="date" 면 시각이 붙어 와도 날짜(yyyy-MM-dd)만 — 그리드는 보통 이 함수를 직접 적지 않고 data-m-datatype="date" 를 준다. 역변환 companion dateFormatter.parse(숫자만 남김) 보유
엔진이 스스로 부르는 서버 주소를 돌려준다 — name 은 'select'(공통코드·첨부목록 조회) 또는 'save'(첨부 등록·수정·삭제). 프로젝트가 mconfig.api 로 정하고, 미지정이면 기본값(/common/select.do · /common/save.do). ★ 모카는 프론트만 제공하므로 엔진에 서버 규약을 박지 않는다 — 자바가 아닌 서버(PHP·닷넷)나 다른 규약을 쓰는 현장은 설정만 바꾸면 된다
CSRF 토큰 조회 — 서버가 쿠키(MOCA-CSRF-TOKEN)로 내려준 값. 화면이 직접 부를 일은 거의 없다(tran.exe·tran.upload 가 자동으로 싣는다). fetch 를 직접 쓸 때만 참고
csrfHeaders([headers])
요청 헤더에 CSRF 토큰(X-CSRF-TOKEN)을 얹어 반환 — 기존 헤더는 보존한다. 상태를 바꾸는 요청(POST/PUT/PATCH/DELETE)은 이 헤더가 없으면 서버가 403 으로 거부한다. 엔진 통신함수는 자동 적용되므로 화면이 fetch 를 직접 쓸 때만 필요
fetch(url, { method:"POST", headers: moca.$g.csrfHeaders({"Content-Type":"application/json"}), body: b })
escapeAttr(str)
escapeHtml 의 속성 문맥용 별칭 — value="…" title="…" 처럼 따옴표 안에 값을 넣을 때. 홑따옴표 속성(value='…')도 안전하다
'<input value="' + moca.$g.escapeAttr(v) + '">'
sanitizeHtml(html)
XSS 무해화 — 굵게·색상 같은 표시용 마크업은 살리고 "실행되는 것"만 제거한다: script/iframe/object/svg 등 실행 태그 · on 으로 시작하는 이벤트 핸들러 속성 전부(onerror·ondrop 등) · javascript: 스크립트 URL · srcdoc. 엔진이 innerHTML 로 외부 데이터를 그릴 때 자동 적용되며(그리드 셀·폼 setValue·탭 제목 등), 화면이 직접 innerHTML 을 조립할 때도 이 함수를 쓴다
el.innerHTML = moca.$g.sanitizeHtml(row.CONTENT)
printHtml(html[, option])
완성된 HTML 한 벌을 인쇄한다(뷰어 공용). 새 창(window.open)은 사용자 제스처가 없으면 차단되고 폰에서는 제스처가 있어도 막히는 경우가 있어, 화면 안 숨은 iframe 으로 인쇄한다 — 어느 기기에서나 같게 동작하고 차단되어 조용히 아무 일도 안 일어나는 일이 없다. 스타일시트·이미지를 다 받은 뒤 인쇄하며(상한 option.timeout, 기본 3000ms), 인쇄가 끝나면 iframe 을 스스로 치운다
파일명(또는 URL)의 확장자로 담당 뷰어의 data-m-type 을 찾는다 — pdf/이미지/텍스트·XML/워드·엑셀·PPT·한글/zip 전부. 확장자만으로 바이너리가 확실한 것(exe·mp4·jar·구형 doc/ppt 등)만 null 이고, 그 밖의 확장자(소스·설정·전문·미지)는 전부 'textviewer' 로 위임한다 — 뷰어가 내용을 보고 바이너리면 내려받기로 전환하기 때문(2026-08-28). 프록시 URL(…?name=파일.pdf)처럼 확장자가 경로 끝이 아닐 수 있으므로 파일명을 우선 준다
파일명(또는 URL)에 맞는 형식 아이콘 경로를 돌려준다 — 첨부목록(fileupload)·압축 트리(zipviewer)가 같이 쓰는 그림이라 어디서 보든 같은 아이콘이다. 형식군 분류는 viewerTypeForFile 을 그대로 따르므로 새 확장자를 뷰어에 보태면 아이콘도 따라온다(분류를 두 곳에 두지 않는다). 그림은 앱 아이콘 16종(pdf·이미지·텍스트·XML·HTML·엑셀·워드·PPT·한글·압축·실행설치·영상음성·폰트·디자인이미지·도면DB·미분류). 구형 .doc·.ppt 나 실행·영상처럼 미리보기는 못 해도 무슨 파일인지는 아는 확장자는 아이콘 전용 표가 따로 답한다 — 아이콘이 답할 질문은 "열 수 있나"가 아니라 "무슨 파일인가"이기 때문
파일을 확장자에 맞는 뷰어로 연다(첨부·게시판 등 파일 목록 공용) — 화면마다 "확장자 보고 뷰어 고르기"를 재작성하지 않는다. 기본은 레이어 모달이고, target(Element 또는 id)을 주면 모달 대신 화면 속 그 영역에 연다(목록 옆 미리보기 패널 — 이전 뷰어는 destroy 후 교체, 높이는 영역이 책임지므로 레이아웃 칸에 둘 것). url 은 same-origin(외부 파일은 서버 프록시 경유), name 은 확장자 판별·제목·내려받기 파일명(뷰어에 data-m-name 으로 전달). 텍스트성·미지 확장자는 텍스트 뷰어로 열리며 내용이 바이너리면 뷰어가 내려받기로 전환한다. false 반환은 확장자만으로 바이너리가 확실한 파일(exe·mp4 등)·url 없음·target 미발견뿐 — 그때만 호출한 화면이 내려받기 등으로 폴백한다
내려받기 파일명을 정한다 — 뷰어·목록이 같은 규칙을 쓴다. 경로 마지막 조각을 그대로 쓰면 서버 프록시 URL 에서 이름이 뭉개진다(첨부를 뷰어로 열어 내려받으니 "googleFileRaw.do" 로 저장돼 확장자가 사라졌다 — 2026-09-18). 순서는 ① 화면이 준 이름(data-m-name — openFileViewer 가 자동 전달) ② URL 의 name 쿼리 ③ 경로 마지막 조각(파일처럼 생겼을 때만 — .do·.jsp 같은 엔드포인트는 이름이 아니다) ④ def
파일을 내려받는다 — a[download] 한 벌을 엔진이 한 곳에서 만든다(뷰어 7종 공용). 파일명은 downloadName 규칙을 따른다. url 이 없으면 아무것도 하지 않고 false 를 반환한다. ★ 다른 출처(cross-origin) 파일은 브라우저가 download 이름을 무시하므로 서버 프록시로 same-origin 을 만들어 준다
moca.$g.downloadFile(_url, row.FILE_NAME)
printUrl(url[, option])
파일 원본을 그대로 인쇄한다(PDF 등) — 화면에 다시 그린 것이 아니라 원본이 나가므로 글자가 글자로 인쇄된다. printHtml 과 같이 숨은 iframe 을 쓴다. 같은 출처(same-origin) 파일만 가능하며, 다른 출처라 iframe 안을 만질 수 없으면 새 탭으로 열어 사람이 인쇄하게 넘긴다(조용히 실패하지 않는다)
moca.$g.printUrl('/files/계약서.pdf')
attachDragScrollbar(scrollEl)
스크롤 영역에 잡고 끌 수 있는 두꺼운 막대를 붙인다(뷰어 공용). 폰의 기본 스크롤바는 얇은 오버레이라 손으로 잡을 수 없고 CSS 로 두껍게 만드는 것도 모바일에서 무시될 수 있어, 엔진이 자기 막대를 그려 어느 기기에서나 같게 동작시킨다 — 막대를 끌거나 빈 곳을 눌러 그 위치로 바로 간다. 스크롤 요소의 부모에 얹으므로 부모가 position:relative 여야 한다. 반환값의 sync() 로 갱신, destroy() 로 제거하며 같은 요소에 두 번 붙지 않는다
moca.$g.attachDragScrollbar(bodyEl)
isNumeric(v)
숫자 여부
isTrue(v)
true 또는 "true" 여부
getNumber(v)
string → 숫자 변환(숫자가 아니면 0 반환)
toTwoChar(v)
1자리 숫자 앞에 0 붙여 2자리로
sortObject(o)
object 를 키 이름으로 정렬하여 반환
shuffleRandom(n)
난수 생성
now([d])
현재(또는 지정 Date)를 yyyyMMddHHmmss+ms+요일 숫자 문자열로 — 유일 id 생성 등에 사용
getType(el)
엘리먼트의 data-m-type 값 반환
getTypeObj(el)
data-m-type 을 가진 가장 가까운 상위 엘리먼트 반환
getAttrObj(el, attr)
속성값(JSON 문자열)을 파싱해 객체로 반환
stopEvent(evt)
이벤트 전파/기본동작 중단
offset(el)
문서 기준 좌표({top,left}) 조회
getSize(el)
크기({width,height}) 조회
fadeTo(el, duration, opacity)
jQuery .fadeTo 대체 — opacity 전이
param(obj)
객체 → URL 쿼리스트링(jQuery $.param 호환 직렬화)
$g.dec
js/decimal.js
add(...values)
더하기 — 인자를 몇 개든 받는다(중첩 호출을 줄이려는 의도). 결과는 문자열
moca.$g.dec.add(0.1, 0.2) // '0.3' — 일반 연산은 0.30000000000000004
sub(a, b)
빼기(a − b)
moca.$g.dec.sub(0.3, 0.1) // '0.2'
mul(...values)
곱하기 — 인자를 몇 개든 받는다. 자릿수는 각 값의 자릿수 합이라 오차가 없다
moca.$g.dec.mul(1234.56, 3) // '3703.68' — 일반 연산은 3703.6800000000003
div(a, b[, scale=10][, mode='half-up'])
나누기 — 나눗셈만은 끊을 자릿수를 정해야 답이 정해진다(1/3 은 끝나지 않는다). b 가 0 이면 오류를 던진다
var regDt = moca.$g.date.getToday('yyyyMMddHHmmss')
format(value[, pattern])
값(yyyyMMdd 등 숫자문자열 또는 Date)을 표시 형식으로. 토큰: yyyy·yy·MM·M·dd·d·HH·mm·ss·E(금)·EEEE(금요일). 토큰이 없으면 그 문자열을 구분자로 본다('-' → 2026-07-31)
moca.$g.date.format('20260731', 'yyyy년 M월 d일 (E)') // '2026년 7월 31일 (금)'
ready([force])
서버시간 동기화 완료를 기다린다(Promise). 엔진이 화면 로드에 걸어 두므로 화면이 부를 일은 거의 없다 — 저장 직전처럼 반드시 서버시각이어야 하는 지점에서만. 서버시각은 백엔드 API 가 아니라 ★HTTP Date 응답 헤더로 받는다(같은 출처 HEAD 1회) — 그래서 해상도는 초 단위이고 표시 시간대는 브라우저 것이다. 2초 타임아웃·실패 시 null(이후 PC 시계 폴백)
월간 달력 매트릭스 — 7열×6주 고정 42칸 [{ymd, dd, dow, inMonth, today}]. 첫 칸은 1일이 속한 주의 일요일(이웃달 포함)이라 월마다 높이가 일정하다. 렌더링은 화면 몫
var cells = moca.$g.date.getMonthMatrix('202607')
getDateRange(el)
그 달력 요소에 적용될 일자범위 → { min, max }. 엔진 기본(19720101~20401231) < mconfig.calendarDateRange < data-m-datemin/datemax
inRange(value, min, max)
값이 범위 안인가 — yyyy/yyyyMM/yyyyMMdd 자릿수에 맞춰 min·max 를 잘라 비교(시각까지 있으면 날짜부만). 그 외 자릿수는 판정 보류(통과)
isDate(ymd)
실재하는 날짜인가(윤년·말일 반영). 구분자(/-.)는 무시
moca.$g.date.isDate('20260231') // false
isTime(hhmm)
HHmm 4자리 시각 형식인가
isLeapYear(ymd)
윤년인가 (yyyy 또는 yyyyMMdd)
pad2(v)
1자리 숫자 앞에 0 을 붙여 2자리로 — 날짜 문자열 조립의 기본 도구
moca.$g.date.pad2(7) // '07'
getLunar(ymd)
양력 → 음력. {y:음력연, m:월(1~12), d:일, leap:윤달 여부} 반환(형식이 아니면 null). 값은 KST 기준이라 한국 음력이다 — 흔한 1900~2100 음력표는 중국 기준이라 합삭이 드는 날 판정이 달라 드물게 하루가 어긋난다(제사·생신에 쓰는 값이라 하루 오차는 오답). 표 대신 합삭·중기를 직접 계산하므로 연도 제한도 없다
공통 조회/저장 — Promise 반환. options: {url, data, callback, progress:false, footer:false, progressMsg, timeout, validate:false, confirm} ★ 저장 확인창은 confirm 옵션으로 — confirm:'변경된 내용을 저장하시겠습니까?' 를 주면 필수값 검사를 통과한 뒤에 확인/취소를 묻고 확인이면 보낸다(취소면 {result:"CANCEL"}, 콜백 안 부름). moca.$g.confirm 으로 감싸 exe 를 부르면 확인 뒤에야 필수값에 막힌다 — page-lint 가 오류로 잡는다. ★ 저장 전 필수값 자동 검사 — data.list 가 그리드의 변경 행(getModifiedJSON)이면 그 그리드의 data-m-required 칸을 보낼 행(C/U)만 검사해, 비었으면 「OO은(는) 필수입력항목입니다」 알림 + 그 칸 포커스 후 보내지 않는다({result:"FAIL", validated:false} 로 끝나고 콜백은 불리지 않는다). 화면이 grid.validate() 를 따로 부르지 않아도 된다 — 끄려면 validate:false. ★ 응답 대기 상한은 기본 30초(moca.$t.timeout)이고 넘기면 안내 후 실패한다 — options.timeout 으로 건별 조정, 0 이면 무제한. ★ 실패 응답(4xx/5xx)이 {result:"FAIL", error:"문구"} 면 그 문구를 알림으로 띄우고 실패로 끝난다(콜백은 불리지 않는다 — 화면이 따로 알리지 않아도 된다)
파일 업로드(키명 formData) — 대기 상한은 기본 무제한(moca.$t.uploadTimeout=0)이다. 업로드 시간은 파일 크기·회선에 비례하므로 고정 상한을 두면 큰 파일이 조용히 끊긴다. 끊을 이유가 분명하면 options.timeout 으로 건별 지정
getResList(res, queryIds[, status])
다중 조회 응답에서 목록 추출 — list 는 콤마구분 queryId명, status 로 행상태 필터(선택)
getResOne(res[, key])
단건 응답 추출 — key 생략 시 res.data1
showProgress([msg][, delay][, limit])
프로그레스 표시 — msg 생략 시 '처리중입니다', delay 생략=기본 지연/0=즉시. limit(ms)을 주면 경과시간을 「12.3초 / 30초」처럼 상한과 함께 보여준다 — 통신 함수가 자기 timeout 을 자동으로 넘기므로 화면이 직접 줄 일은 거의 없다
setProgressMsg(msg)
프로그레스 메시지 변경(지연표시 대기중이면 표시 시점에 반영)
hideProgress([force])
프로그레스 닫기 — force=true 면 진행건수와 무관하게 강제
setFooterStatus(msg)
메인 푸터 우측 상태영역(#footerStatus)에 텍스트 표시
ViewGrid
js/viewgrid.js
new ViewGrid(div)
div 의 자식 div[data-m-col] 들이 컬럼 선언(data-m-col/-label/-width/-sortable/-filterable/-displayfunction + class tal·tar) — 인라인 핸들러가 없어 scopeId 불필요
var g = new ViewGrid(div); g.drawGrid(rows)
drawGrid(rows)
행 배열을 그린다 — rows 는 {컬럼id: 정렬용 원본값, "컬럼id__d": 표시문자열} 규약(excelviewer §77-3 과 동일). 정렬·필터 상태는 초기화된다
redrawGrid()
현재 정렬·필터 상태를 유지한 재렌더(칸 크기 변화 대응)
.list
drawGrid 로 받은 원본 배열 — displayfunction 브리지가 realIndex 로 읽는다
destroy()
문서 리스너 해제 + DOM 비움
MocaSwiper
plugins/swiper.js
loop(el, opt)
슬라이드 3장 무한 좌우 스와이퍼 생성 — el 은 .swiper-wrapper > .swiper-slide 3장을 품은 컨테이너. opt: { autoHeight(가운데 슬라이드 높이 반영), onShift(dir — 이동 확정 시 +1/-1), renderSlide(slideEl, offset — 슬라이드 채우기, offset -1|0|+1) }. 반환 핸들: next()/prev()(버튼 이동 — 스와이프와 동일 경로) · refresh()(3장 재렌더+높이 재측정) · destroy() · swiper(원본 인스턴스). ⚠ 슬라이드 DOM 재렌더는 반드시 renderSlide 호출 시점에만 — onShift 안에서 직접 그리면 진행 중 전환이 끊긴다
var _cal = MocaSwiper.loop($p.get('wpCalSwiper'), { autoHeight:true, onShift:function(pDir){…}, renderSlide:function(pEl,pOff){…} })
화면 스코프 $p
화면마다 하나씩 생기는 스코프입니다. 화면의 모든 함수·변수는 $p 하위에 붙입니다.
속성
frame
이 화면의 frame 엘리먼트. frame 엘리먼트에서 그 화면의 스코프를 얻을 때는 getScope() 를 쓴다(예: $p.getParent().getScope())
parameter
이 화면을 열 때 넘어온 파라미터 원본(없으면 undefined). 읽을 때는 getParameter() 를 쓴다
scopeId
이 스코프의 전역 식별자(예: 'm$3') — mocaTop[scopeId](같은 오리진 최상위 창, 보통 top) 로 접근 가능
scopePath
부모부터의 스코프 경로 문자열
ispageloaded
화면 로드(onpageload) 완료 여부 — onpageload 를 정의하지 않은 화면도 로드 완료 시 true
메서드
get(id)
이 화면 안에서 id 로 컴포넌트 인스턴스(없으면 엘리먼트) 반환. 중복 id 는 콘솔 경고
$p.get('grd_main').drawGrid(list)
findAllAttr(attr, value[, idx])
이 화면 안에서 속성=값 인 엘리먼트들 반환(idx 지정 시 그 하나)
$p.findAllAttr('data-m-mobileview', 'pop')
findAll(selector)
이 화면 안에서 CSS 셀렉터로 검색
getParent()
부모 화면의 frame 엘리먼트를 돌려준다(최상위 화면이면 null). 부모 화면의 컴포넌트나 함수를 쓰려면 여기에 getScope() 를 이어 붙인다 — 엘리먼트의 내부 속성(.scope 등)을 직접 읽지 않는다
// 부모 화면의 컴포넌트 값 읽기
var _pct = $p.getParent().getScope().get('ipt_percent').getValue();
// 부모 화면의 함수 호출
$p.getParent().getScope().fn_search();
// 부모 화면 자체를 새로고침
frame.reload($p.getParent());
getParameter()
이 화면을 열 때 넘어온 값을 돌려준다(없으면 빈 객체 {}). 탭으로 열렸든 팝업으로 열렸든 받는 방법은 같아서, 화면은 자기가 어떻게 열렸는지 몰라도 된다 — 탭 openTab(url, param) · 팝업 $p.openPop({data:…}) · frame.load 3번째 인자가 모두 이 자리로 들어온다. 값이 없어도 {} 라서 "파라미터가 있는지" 판정에는 쓰지 말고(항상 참) 개별 키의 값으로 판정한다
레이어 팝업을 연다. url(필수) · title · titleIcon(제목 앞 아이콘 주소 — 파일 팝업은 moca.$g.fileIconSrc(name) 를 넘기면 형식 아이콘이 붙고 제목 앞 색막대는 감춰진다) · width · height · modal("true"/"false") · data · callback · closeBtn(헤더 우상단 ✕, 기본 표시 — false 면 안 그린다) · maxBtn(헤더 □ 최대화 — 누르거나 헤더를 더블클릭하면 창 가득 ↔ 원래 크기, 기본 표시 — false 면 안 그린다) 을 옵션으로 받는다. data 에 담아 보낸 값은 팝업 화면이 $p.getParameter() 로 꺼내 쓰고, 팝업이 $p.close(결과) 로 닫으면 callback(결과) 이 호출된다. 높이는 보통 지정하지 않고 팝업 페이지가 data-m-height 로 정한다
$p.openPop({
url: '/system/demo/ui/page/POP_MENUSEARCH.html',
title: '메뉴 검색',
width: '640px',
data: { menuParam: '게시' }, // 팝업이 $p.getParameter() 로 받는다
callback: function(row) { // 팝업이 $p.close(row) 로 닫았을 때
$p.get('ipt_menuNm').setValue(row.MENU_NM);
}
});
openWin(option)
브라우저 창 팝업(window.open)을 연다 — 레이어 팝업(openPop)의 새 창 버전이라 옵션·규약이 같다(팝업 페이지는 한 벌만 두고 여는 쪽만 바꾼다). url(필수) · title · width/height(숫자 px, 기본 1024×700) · data · callback · name(같은 이름이면 그 창을 재사용). 새 창에서도 $p.getParameter() / $p.close(결과) 가 그대로 동작하고, 창을 X 로 닫으면 취소다. 브라우저가 팝업을 차단하면 안내 후 null 을 반환한다. 새 창은 듀얼 모니터·나란히 보기처럼 원래 화면을 막으면 안 될 때 쓰고, 그 외에는 레이어가 낫다
이 화면을 닫는다. 팝업이면 팝업이 닫히고(레이어·새 창 모두) 탭으로 연 화면이면 탭이 닫히므로, 화면 쪽에서 셋을 구분할 필요가 없다. 값을 넘기면 "확정"이라 이 화면을 연 쪽의 callback 이 그 값과 함께 호출되고, 그냥 close() 로 닫으면 "취소"라 callback 이 호출되지 않는다. 저장만 하고 닫는 팝업처럼 돌려줄 데이터는 없지만 처리됐다는 사실은 알려야 한다면 close(true) 로 아무 값이나 넘기면 된다
$p.close(_row); // 확정 — 연 쪽 callback(_row) 호출
$p.close(); // 취소 — callback 호출 안 함
$p.close(true); // 돌려줄 값은 없지만 "처리됐다"고 알릴 때
code(config[, callback])
공통 코드 바인더 — 콤보/서치콤보/그리드셀에 코드 데이터를 선언형으로 세팅(대상 검색이 이 화면으로 한정). config 는 { 컴포넌트id 또는 "그리드id.셀id": 옵션 }. 옵션은 두 모양뿐이다 — 공통코드 그룹 { code:'GROUP_CD' } 또는 업무 쿼리 { queryId:'selectXxxCombo', body:{…} }(행의 필드는 cd/nm, 다르면 cdField/nmField). 여기에 allOption·selectedValue 를 더할 수 있다. ★ 이 밖의 키(table·column·codeId 등)는 엔진이 오류 없이 무시해 콤보가 빈 채로 뜬다 — 쓰지 않는다. 호출은 화면 스크립트(첫 <script>)의 onpageload 안에서 한다