ninegrid2 6.1343.0 → 6.1345.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.cjs.js +11 -31
- package/dist/bundle.esm.js +11 -31
- package/dist/nx/_nxDiv.js +6 -0
- package/dist/nx/_nxDiv2.js +57 -36
- package/dist/nx/nxButtons.js +3 -29
- package/dist/nx/nxEditor.js +3 -3
- package/package.json +1 -1
- package/src/nx/_nxDiv.js +6 -0
- package/src/nx/_nxDiv2.js +145 -0
- package/src/nx/nxButtons.js +3 -29
- package/src/nx/nxEditor.js +3 -3
package/dist/bundle.cjs.js
CHANGED
|
@@ -28533,6 +28533,12 @@ class nxDiv extends HTMLElement {
|
|
|
28533
28533
|
if (bChanged) this.#changed(bChanged);
|
|
28534
28534
|
};
|
|
28535
28535
|
|
|
28536
|
+
clearData = (bChanged) => {
|
|
28537
|
+
|
|
28538
|
+
|
|
28539
|
+
this.#changed(false);
|
|
28540
|
+
};
|
|
28541
|
+
|
|
28536
28542
|
initData = (jsonData) => {
|
|
28537
28543
|
this.setData(jsonData);
|
|
28538
28544
|
this.#changed(false);
|
|
@@ -28872,7 +28878,7 @@ class nxPanel extends nxDiv {
|
|
|
28872
28878
|
|
|
28873
28879
|
customElements.define("nx-panel", nxPanel);
|
|
28874
28880
|
|
|
28875
|
-
class nxButtons extends
|
|
28881
|
+
class nxButtons extends nxDiv2 {
|
|
28876
28882
|
|
|
28877
28883
|
constructor() {
|
|
28878
28884
|
super();
|
|
@@ -28892,36 +28898,10 @@ class nxButtons extends nxDiv {
|
|
|
28892
28898
|
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
28893
28899
|
${ninegrid.getCustomPath(this,"nxButtons.css")}
|
|
28894
28900
|
</style>
|
|
28895
|
-
|
|
28896
|
-
${this.originContents}
|
|
28901
|
+
<slot></slot>
|
|
28897
28902
|
`;
|
|
28898
28903
|
|
|
28899
|
-
//console.log(htmlTmpl);
|
|
28900
|
-
|
|
28901
28904
|
target.appendChild(htmlTmpl.content.cloneNode(true));
|
|
28902
|
-
/**
|
|
28903
|
-
target.addEventListener('click', (e) => {
|
|
28904
|
-
|
|
28905
|
-
const btn = e.target.closest('button');
|
|
28906
|
-
if (!btn) return;
|
|
28907
|
-
|
|
28908
|
-
//const actionName = btn.getAttribute('on-click') || btn.getAttribute('onClick') || btn.getAttribute('onclick');
|
|
28909
|
-
|
|
28910
|
-
const actionName = btn.getAttribute('on-click');
|
|
28911
|
-
|
|
28912
|
-
console.log(btn, actionName, this[actionName])
|
|
28913
|
-
console.log(typeof this[actionName])
|
|
28914
|
-
if (actionName) {
|
|
28915
|
-
// 1. 먼저 엘리먼트 자체(this)에 해당 이름의 함수가 있는지 확인
|
|
28916
|
-
if (typeof this[actionName] === 'function') {
|
|
28917
|
-
this[actionName](e);
|
|
28918
|
-
}
|
|
28919
|
-
// 2. 없으면 전역 window에서 확인
|
|
28920
|
-
else if (typeof window[actionName] === 'function') {
|
|
28921
|
-
window[actionName](e);
|
|
28922
|
-
}
|
|
28923
|
-
}
|
|
28924
|
-
}); */
|
|
28925
28905
|
}
|
|
28926
28906
|
}
|
|
28927
28907
|
|
|
@@ -55263,7 +55243,7 @@ class nxEditor extends nxDiv {
|
|
|
55263
55243
|
|
|
55264
55244
|
<div class="menu-bar">
|
|
55265
55245
|
<button type="button" data-cmd="bold" title="굵게 (Ctrl+B)"><b>B</b></button>
|
|
55266
|
-
<button type="button" data-cmd="italic" title="기울임 (Ctrl+I)"><
|
|
55246
|
+
<button type="button" data-cmd="italic" title="기울임 (Ctrl+I)"><em>I</em></button>
|
|
55267
55247
|
<button type="button" data-cmd="underline" title="밑줄 (Ctrl+U)"><u>U</u></button>
|
|
55268
55248
|
<button type="button" data-cmd="strike" title="취소선"><s>S</s></button>
|
|
55269
55249
|
|
|
@@ -55284,8 +55264,8 @@ class nxEditor extends nxDiv {
|
|
|
55284
55264
|
<button type="button" data-align="center" title="가운데 정렬"><i class="icon-center"></i></button>
|
|
55285
55265
|
<button type="button" data-align="right" title="오른쪽 정렬"><i class="icon-right"></i></button>
|
|
55286
55266
|
|
|
55287
|
-
<button type="button" data-cmd="bulletList" title="글머리 기호"><i class="icon-
|
|
55288
|
-
<button type="button" data-cmd="orderedList" title="번호 매기기"><i class="icon-
|
|
55267
|
+
<button type="button" data-cmd="bulletList" title="글머리 기호"><i class="icon-ul"></i></button>
|
|
55268
|
+
<button type="button" data-cmd="orderedList" title="번호 매기기"><i class="icon-ol"></i></button>
|
|
55289
55269
|
|
|
55290
55270
|
<button type="button" id="img-btn" title="이미지 삽입"><i class="icon-image"></i></button>
|
|
55291
55271
|
<button type="button" data-cmd="undo" title="실행 취소(Ctrl+Z)"><i class="icon-undo"></i></button>
|
package/dist/bundle.esm.js
CHANGED
|
@@ -28529,6 +28529,12 @@ class nxDiv extends HTMLElement {
|
|
|
28529
28529
|
if (bChanged) this.#changed(bChanged);
|
|
28530
28530
|
};
|
|
28531
28531
|
|
|
28532
|
+
clearData = (bChanged) => {
|
|
28533
|
+
|
|
28534
|
+
|
|
28535
|
+
this.#changed(false);
|
|
28536
|
+
};
|
|
28537
|
+
|
|
28532
28538
|
initData = (jsonData) => {
|
|
28533
28539
|
this.setData(jsonData);
|
|
28534
28540
|
this.#changed(false);
|
|
@@ -28868,7 +28874,7 @@ class nxPanel extends nxDiv {
|
|
|
28868
28874
|
|
|
28869
28875
|
customElements.define("nx-panel", nxPanel);
|
|
28870
28876
|
|
|
28871
|
-
class nxButtons extends
|
|
28877
|
+
class nxButtons extends nxDiv2 {
|
|
28872
28878
|
|
|
28873
28879
|
constructor() {
|
|
28874
28880
|
super();
|
|
@@ -28888,36 +28894,10 @@ class nxButtons extends nxDiv {
|
|
|
28888
28894
|
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
28889
28895
|
${ninegrid.getCustomPath(this,"nxButtons.css")}
|
|
28890
28896
|
</style>
|
|
28891
|
-
|
|
28892
|
-
${this.originContents}
|
|
28897
|
+
<slot></slot>
|
|
28893
28898
|
`;
|
|
28894
28899
|
|
|
28895
|
-
//console.log(htmlTmpl);
|
|
28896
|
-
|
|
28897
28900
|
target.appendChild(htmlTmpl.content.cloneNode(true));
|
|
28898
|
-
/**
|
|
28899
|
-
target.addEventListener('click', (e) => {
|
|
28900
|
-
|
|
28901
|
-
const btn = e.target.closest('button');
|
|
28902
|
-
if (!btn) return;
|
|
28903
|
-
|
|
28904
|
-
//const actionName = btn.getAttribute('on-click') || btn.getAttribute('onClick') || btn.getAttribute('onclick');
|
|
28905
|
-
|
|
28906
|
-
const actionName = btn.getAttribute('on-click');
|
|
28907
|
-
|
|
28908
|
-
console.log(btn, actionName, this[actionName])
|
|
28909
|
-
console.log(typeof this[actionName])
|
|
28910
|
-
if (actionName) {
|
|
28911
|
-
// 1. 먼저 엘리먼트 자체(this)에 해당 이름의 함수가 있는지 확인
|
|
28912
|
-
if (typeof this[actionName] === 'function') {
|
|
28913
|
-
this[actionName](e);
|
|
28914
|
-
}
|
|
28915
|
-
// 2. 없으면 전역 window에서 확인
|
|
28916
|
-
else if (typeof window[actionName] === 'function') {
|
|
28917
|
-
window[actionName](e);
|
|
28918
|
-
}
|
|
28919
|
-
}
|
|
28920
|
-
}); */
|
|
28921
28901
|
}
|
|
28922
28902
|
}
|
|
28923
28903
|
|
|
@@ -55259,7 +55239,7 @@ class nxEditor extends nxDiv {
|
|
|
55259
55239
|
|
|
55260
55240
|
<div class="menu-bar">
|
|
55261
55241
|
<button type="button" data-cmd="bold" title="굵게 (Ctrl+B)"><b>B</b></button>
|
|
55262
|
-
<button type="button" data-cmd="italic" title="기울임 (Ctrl+I)"><
|
|
55242
|
+
<button type="button" data-cmd="italic" title="기울임 (Ctrl+I)"><em>I</em></button>
|
|
55263
55243
|
<button type="button" data-cmd="underline" title="밑줄 (Ctrl+U)"><u>U</u></button>
|
|
55264
55244
|
<button type="button" data-cmd="strike" title="취소선"><s>S</s></button>
|
|
55265
55245
|
|
|
@@ -55280,8 +55260,8 @@ class nxEditor extends nxDiv {
|
|
|
55280
55260
|
<button type="button" data-align="center" title="가운데 정렬"><i class="icon-center"></i></button>
|
|
55281
55261
|
<button type="button" data-align="right" title="오른쪽 정렬"><i class="icon-right"></i></button>
|
|
55282
55262
|
|
|
55283
|
-
<button type="button" data-cmd="bulletList" title="글머리 기호"><i class="icon-
|
|
55284
|
-
<button type="button" data-cmd="orderedList" title="번호 매기기"><i class="icon-
|
|
55263
|
+
<button type="button" data-cmd="bulletList" title="글머리 기호"><i class="icon-ul"></i></button>
|
|
55264
|
+
<button type="button" data-cmd="orderedList" title="번호 매기기"><i class="icon-ol"></i></button>
|
|
55285
55265
|
|
|
55286
55266
|
<button type="button" id="img-btn" title="이미지 삽입"><i class="icon-image"></i></button>
|
|
55287
55267
|
<button type="button" data-cmd="undo" title="실행 취소(Ctrl+Z)"><i class="icon-undo"></i></button>
|
package/dist/nx/_nxDiv.js
CHANGED
|
@@ -100,6 +100,12 @@ export class nxDiv extends HTMLElement {
|
|
|
100
100
|
if (bChanged) this.#changed(bChanged);
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
+
clearData = (bChanged) => {
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
this.#changed(false);
|
|
107
|
+
};
|
|
108
|
+
|
|
103
109
|
initData = (jsonData) => {
|
|
104
110
|
this.setData(jsonData);
|
|
105
111
|
this.#changed(false);
|
package/dist/nx/_nxDiv2.js
CHANGED
|
@@ -1,32 +1,51 @@
|
|
|
1
1
|
import ninegrid from "../index.js";
|
|
2
2
|
|
|
3
|
-
export class nxDiv2 extends HTMLElement
|
|
4
|
-
{
|
|
3
|
+
export class nxDiv2 extends HTMLElement {
|
|
5
4
|
originContents;
|
|
6
5
|
#isInitialized = false;
|
|
6
|
+
#root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
|
|
7
7
|
|
|
8
|
-
constructor
|
|
8
|
+
constructor() {
|
|
9
9
|
super();
|
|
10
|
-
|
|
10
|
+
// constructor에서는 속성을 읽을 수 없으므로 초기화만 준비합니다.
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
connectedCallback() {
|
|
14
14
|
if (!this.#isInitialized) {
|
|
15
|
+
// 1. 여기서 속성을 읽어 Shadow DOM 사용 여부를 결정합니다.
|
|
16
|
+
// use-shadow 속성이 "false"가 아닐 때만 Shadow DOM을 생성 (기본값 true)
|
|
17
|
+
const useShadow = this.getAttribute("use-shadow") !== "false";
|
|
18
|
+
|
|
19
|
+
if (useShadow && !this.shadowRoot) {
|
|
20
|
+
this.attachShadow({ mode: 'open' });
|
|
21
|
+
this.#root = this.shadowRoot;
|
|
22
|
+
} else {
|
|
23
|
+
this.#root = this;
|
|
24
|
+
}
|
|
25
|
+
|
|
15
26
|
this.#init();
|
|
16
|
-
this.#isInitialized = true;
|
|
27
|
+
this.#isInitialized = true;
|
|
17
28
|
return true;
|
|
18
29
|
}
|
|
19
|
-
|
|
20
30
|
return false;
|
|
21
31
|
}
|
|
22
32
|
|
|
33
|
+
// 자식 클래스에서 접근 가능하도록 getter 제공
|
|
34
|
+
get root() {
|
|
35
|
+
return this.#root || this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
|
|
39
|
+
#getElements() {
|
|
40
|
+
// ShadowRoot가 있으면 shadowRoot에서, 없으면 본체(this)에서 찾음
|
|
41
|
+
return ninegrid.querySelectorAll("input[name], textarea[name], select[name], nx-editor[name]", this.#root);
|
|
42
|
+
}
|
|
43
|
+
|
|
23
44
|
getData = () => {
|
|
24
45
|
const jsonData = {};
|
|
25
|
-
|
|
26
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
27
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
46
|
+
this.#getElements().forEach(el => {
|
|
28
47
|
const key = el.name;
|
|
29
|
-
if (!key) return;
|
|
48
|
+
if (!key) return;
|
|
30
49
|
|
|
31
50
|
let value;
|
|
32
51
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -35,57 +54,58 @@ export class nxDiv2 extends HTMLElement
|
|
|
35
54
|
value = el.value;
|
|
36
55
|
}
|
|
37
56
|
|
|
38
|
-
// 중복 name을 대비한 배열 처리
|
|
39
57
|
if (jsonData[key]) {
|
|
40
|
-
if (!Array.isArray(jsonData[key]))
|
|
41
|
-
jsonData[key] = [jsonData[key]];
|
|
42
|
-
}
|
|
58
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
43
59
|
jsonData[key].push(value);
|
|
44
60
|
} else {
|
|
45
61
|
jsonData[key] = value;
|
|
46
62
|
}
|
|
47
63
|
});
|
|
48
|
-
|
|
49
64
|
return jsonData;
|
|
50
65
|
};
|
|
51
66
|
|
|
52
67
|
setData = (jsonData) => {
|
|
53
|
-
|
|
68
|
+
this.#getElements().forEach(el => {
|
|
54
69
|
el.removeEventListener("input", this.#changeHandler);
|
|
55
70
|
el.addEventListener("input", this.#changeHandler);
|
|
56
71
|
});
|
|
57
72
|
|
|
58
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
59
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
73
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
62
74
|
|
|
63
75
|
let bChanged = false;
|
|
64
|
-
|
|
76
|
+
this.#getElements().forEach(el => {
|
|
65
77
|
const key = el.name;
|
|
78
|
+
//console.log(el.tagName, key, el.name);
|
|
79
|
+
|
|
66
80
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
67
81
|
|
|
68
82
|
const value = jsonData[key];
|
|
69
83
|
|
|
70
|
-
|
|
71
|
-
|
|
84
|
+
const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
|
|
85
|
+
|
|
86
|
+
if (inputTags.includes(el.tagName)) {
|
|
72
87
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
73
|
-
|
|
74
|
-
el.checked
|
|
88
|
+
const isChecked = (String(el.value) === String(value));
|
|
89
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
90
|
+
el.checked = isChecked;
|
|
75
91
|
} else {
|
|
76
92
|
if (el.value !== value) bChanged = true;
|
|
77
93
|
el.value = value;
|
|
78
94
|
}
|
|
79
95
|
} else {
|
|
80
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
81
96
|
if (el.textContent !== value) bChanged = true;
|
|
82
97
|
el.textContent = value;
|
|
83
98
|
}
|
|
84
99
|
});
|
|
85
|
-
|
|
86
100
|
if (bChanged) this.#changed(bChanged);
|
|
87
101
|
};
|
|
88
102
|
|
|
103
|
+
clearData = (bChanged) => {
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
this.#changed(false);
|
|
107
|
+
};
|
|
108
|
+
|
|
89
109
|
initData = (jsonData) => {
|
|
90
110
|
this.setData(jsonData);
|
|
91
111
|
this.#changed(false);
|
|
@@ -104,21 +124,22 @@ export class nxDiv2 extends HTMLElement
|
|
|
104
124
|
}
|
|
105
125
|
|
|
106
126
|
#init = () => {
|
|
107
|
-
|
|
108
|
-
//console.log(this);
|
|
109
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* css style 적용
|
|
113
|
-
*/
|
|
127
|
+
/** CSS style 적용 */
|
|
114
128
|
for (const attr of this.attributes) {
|
|
115
129
|
if (attr.name.startsWith("css-")) {
|
|
116
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
117
130
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
118
131
|
}
|
|
119
132
|
}
|
|
120
133
|
|
|
134
|
+
//console.log("=========");
|
|
135
|
+
//console.log(this.innerHTML.trim());
|
|
136
|
+
|
|
121
137
|
this.originContents = this.innerHTML.trim();
|
|
122
|
-
this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
138
|
+
//this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
139
|
+
|
|
140
|
+
// 만약 순수 nx-div로만 쓰일 경우(상속 x), 내용을 shadow에 채워줌
|
|
141
|
+
if (this.shadowRoot && this.tagName.toLowerCase() === 'nx-div') {
|
|
142
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
143
|
+
}
|
|
123
144
|
};
|
|
124
145
|
}
|
package/dist/nx/nxButtons.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ninegrid from "../index.js";
|
|
2
|
-
import {nxDiv} from "./
|
|
2
|
+
import {nxDiv} from "./_nxDiv2.js";
|
|
3
3
|
|
|
4
|
-
class nxButtons extends
|
|
4
|
+
class nxButtons extends nxDiv2 {
|
|
5
5
|
|
|
6
6
|
constructor() {
|
|
7
7
|
super();
|
|
@@ -21,36 +21,10 @@ class nxButtons extends nxDiv {
|
|
|
21
21
|
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
22
22
|
${ninegrid.getCustomPath(this,"nxButtons.css")}
|
|
23
23
|
</style>
|
|
24
|
-
|
|
25
|
-
${this.originContents}
|
|
24
|
+
<slot></slot>
|
|
26
25
|
`;
|
|
27
26
|
|
|
28
|
-
//console.log(htmlTmpl);
|
|
29
|
-
|
|
30
27
|
target.appendChild(htmlTmpl.content.cloneNode(true));
|
|
31
|
-
/**
|
|
32
|
-
target.addEventListener('click', (e) => {
|
|
33
|
-
|
|
34
|
-
const btn = e.target.closest('button');
|
|
35
|
-
if (!btn) return;
|
|
36
|
-
|
|
37
|
-
//const actionName = btn.getAttribute('on-click') || btn.getAttribute('onClick') || btn.getAttribute('onclick');
|
|
38
|
-
|
|
39
|
-
const actionName = btn.getAttribute('on-click');
|
|
40
|
-
|
|
41
|
-
console.log(btn, actionName, this[actionName])
|
|
42
|
-
console.log(typeof this[actionName])
|
|
43
|
-
if (actionName) {
|
|
44
|
-
// 1. 먼저 엘리먼트 자체(this)에 해당 이름의 함수가 있는지 확인
|
|
45
|
-
if (typeof this[actionName] === 'function') {
|
|
46
|
-
this[actionName](e);
|
|
47
|
-
}
|
|
48
|
-
// 2. 없으면 전역 window에서 확인
|
|
49
|
-
else if (typeof window[actionName] === 'function') {
|
|
50
|
-
window[actionName](e);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}); */
|
|
54
28
|
}
|
|
55
29
|
}
|
|
56
30
|
|
package/dist/nx/nxEditor.js
CHANGED
|
@@ -75,7 +75,7 @@ class nxEditor extends nxDiv {
|
|
|
75
75
|
|
|
76
76
|
<div class="menu-bar">
|
|
77
77
|
<button type="button" data-cmd="bold" title="굵게 (Ctrl+B)"><b>B</b></button>
|
|
78
|
-
<button type="button" data-cmd="italic" title="기울임 (Ctrl+I)"><
|
|
78
|
+
<button type="button" data-cmd="italic" title="기울임 (Ctrl+I)"><em>I</em></button>
|
|
79
79
|
<button type="button" data-cmd="underline" title="밑줄 (Ctrl+U)"><u>U</u></button>
|
|
80
80
|
<button type="button" data-cmd="strike" title="취소선"><s>S</s></button>
|
|
81
81
|
|
|
@@ -96,8 +96,8 @@ class nxEditor extends nxDiv {
|
|
|
96
96
|
<button type="button" data-align="center" title="가운데 정렬"><i class="icon-center"></i></button>
|
|
97
97
|
<button type="button" data-align="right" title="오른쪽 정렬"><i class="icon-right"></i></button>
|
|
98
98
|
|
|
99
|
-
<button type="button" data-cmd="bulletList" title="글머리 기호"><i class="icon-
|
|
100
|
-
<button type="button" data-cmd="orderedList" title="번호 매기기"><i class="icon-
|
|
99
|
+
<button type="button" data-cmd="bulletList" title="글머리 기호"><i class="icon-ul"></i></button>
|
|
100
|
+
<button type="button" data-cmd="orderedList" title="번호 매기기"><i class="icon-ol"></i></button>
|
|
101
101
|
|
|
102
102
|
<button type="button" id="img-btn" title="이미지 삽입"><i class="icon-image"></i></button>
|
|
103
103
|
<button type="button" data-cmd="undo" title="실행 취소(Ctrl+Z)"><i class="icon-undo"></i></button>
|
package/package.json
CHANGED
package/src/nx/_nxDiv.js
CHANGED
|
@@ -100,6 +100,12 @@ export class nxDiv extends HTMLElement {
|
|
|
100
100
|
if (bChanged) this.#changed(bChanged);
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
+
clearData = (bChanged) => {
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
this.#changed(false);
|
|
107
|
+
};
|
|
108
|
+
|
|
103
109
|
initData = (jsonData) => {
|
|
104
110
|
this.setData(jsonData);
|
|
105
111
|
this.#changed(false);
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import ninegrid from "../index.js";
|
|
2
|
+
|
|
3
|
+
export class nxDiv2 extends HTMLElement {
|
|
4
|
+
originContents;
|
|
5
|
+
#isInitialized = false;
|
|
6
|
+
#root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
// constructor에서는 속성을 읽을 수 없으므로 초기화만 준비합니다.
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
connectedCallback() {
|
|
14
|
+
if (!this.#isInitialized) {
|
|
15
|
+
// 1. 여기서 속성을 읽어 Shadow DOM 사용 여부를 결정합니다.
|
|
16
|
+
// use-shadow 속성이 "false"가 아닐 때만 Shadow DOM을 생성 (기본값 true)
|
|
17
|
+
const useShadow = this.getAttribute("use-shadow") !== "false";
|
|
18
|
+
|
|
19
|
+
if (useShadow && !this.shadowRoot) {
|
|
20
|
+
this.attachShadow({ mode: 'open' });
|
|
21
|
+
this.#root = this.shadowRoot;
|
|
22
|
+
} else {
|
|
23
|
+
this.#root = this;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
this.#init();
|
|
27
|
+
this.#isInitialized = true;
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 자식 클래스에서 접근 가능하도록 getter 제공
|
|
34
|
+
get root() {
|
|
35
|
+
return this.#root || this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
|
|
39
|
+
#getElements() {
|
|
40
|
+
// ShadowRoot가 있으면 shadowRoot에서, 없으면 본체(this)에서 찾음
|
|
41
|
+
return ninegrid.querySelectorAll("input[name], textarea[name], select[name], nx-editor[name]", this.#root);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getData = () => {
|
|
45
|
+
const jsonData = {};
|
|
46
|
+
this.#getElements().forEach(el => {
|
|
47
|
+
const key = el.name;
|
|
48
|
+
if (!key) return;
|
|
49
|
+
|
|
50
|
+
let value;
|
|
51
|
+
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
52
|
+
value = el.checked;
|
|
53
|
+
} else {
|
|
54
|
+
value = el.value;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (jsonData[key]) {
|
|
58
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
59
|
+
jsonData[key].push(value);
|
|
60
|
+
} else {
|
|
61
|
+
jsonData[key] = value;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return jsonData;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
setData = (jsonData) => {
|
|
68
|
+
this.#getElements().forEach(el => {
|
|
69
|
+
el.removeEventListener("input", this.#changeHandler);
|
|
70
|
+
el.addEventListener("input", this.#changeHandler);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
74
|
+
|
|
75
|
+
let bChanged = false;
|
|
76
|
+
this.#getElements().forEach(el => {
|
|
77
|
+
const key = el.name;
|
|
78
|
+
//console.log(el.tagName, key, el.name);
|
|
79
|
+
|
|
80
|
+
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
81
|
+
|
|
82
|
+
const value = jsonData[key];
|
|
83
|
+
|
|
84
|
+
const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
|
|
85
|
+
|
|
86
|
+
if (inputTags.includes(el.tagName)) {
|
|
87
|
+
if (el.type === "checkbox" || el.type === "radio") {
|
|
88
|
+
const isChecked = (String(el.value) === String(value));
|
|
89
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
90
|
+
el.checked = isChecked;
|
|
91
|
+
} else {
|
|
92
|
+
if (el.value !== value) bChanged = true;
|
|
93
|
+
el.value = value;
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
if (el.textContent !== value) bChanged = true;
|
|
97
|
+
el.textContent = value;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
if (bChanged) this.#changed(bChanged);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
clearData = (bChanged) => {
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
this.#changed(false);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
initData = (jsonData) => {
|
|
110
|
+
this.setData(jsonData);
|
|
111
|
+
this.#changed(false);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
#changed = (v) => {
|
|
115
|
+
const parent = this.closest(".detail-wrapper");
|
|
116
|
+
if (parent) {
|
|
117
|
+
const el = parent.querySelector("nx-title2");
|
|
118
|
+
if (el) el.changed = v;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
#changeHandler = (e) => {
|
|
123
|
+
this.#changed(true);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#init = () => {
|
|
127
|
+
/** CSS style 적용 */
|
|
128
|
+
for (const attr of this.attributes) {
|
|
129
|
+
if (attr.name.startsWith("css-")) {
|
|
130
|
+
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//console.log("=========");
|
|
135
|
+
//console.log(this.innerHTML.trim());
|
|
136
|
+
|
|
137
|
+
this.originContents = this.innerHTML.trim();
|
|
138
|
+
//this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
139
|
+
|
|
140
|
+
// 만약 순수 nx-div로만 쓰일 경우(상속 x), 내용을 shadow에 채워줌
|
|
141
|
+
if (this.shadowRoot && this.tagName.toLowerCase() === 'nx-div') {
|
|
142
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
package/src/nx/nxButtons.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ninegrid from "../index.js";
|
|
2
|
-
import {nxDiv} from "./
|
|
2
|
+
import {nxDiv} from "./_nxDiv2.js";
|
|
3
3
|
|
|
4
|
-
class nxButtons extends
|
|
4
|
+
class nxButtons extends nxDiv2 {
|
|
5
5
|
|
|
6
6
|
constructor() {
|
|
7
7
|
super();
|
|
@@ -21,36 +21,10 @@ class nxButtons extends nxDiv {
|
|
|
21
21
|
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
22
22
|
${ninegrid.getCustomPath(this,"nxButtons.css")}
|
|
23
23
|
</style>
|
|
24
|
-
|
|
25
|
-
${this.originContents}
|
|
24
|
+
<slot></slot>
|
|
26
25
|
`;
|
|
27
26
|
|
|
28
|
-
//console.log(htmlTmpl);
|
|
29
|
-
|
|
30
27
|
target.appendChild(htmlTmpl.content.cloneNode(true));
|
|
31
|
-
/**
|
|
32
|
-
target.addEventListener('click', (e) => {
|
|
33
|
-
|
|
34
|
-
const btn = e.target.closest('button');
|
|
35
|
-
if (!btn) return;
|
|
36
|
-
|
|
37
|
-
//const actionName = btn.getAttribute('on-click') || btn.getAttribute('onClick') || btn.getAttribute('onclick');
|
|
38
|
-
|
|
39
|
-
const actionName = btn.getAttribute('on-click');
|
|
40
|
-
|
|
41
|
-
console.log(btn, actionName, this[actionName])
|
|
42
|
-
console.log(typeof this[actionName])
|
|
43
|
-
if (actionName) {
|
|
44
|
-
// 1. 먼저 엘리먼트 자체(this)에 해당 이름의 함수가 있는지 확인
|
|
45
|
-
if (typeof this[actionName] === 'function') {
|
|
46
|
-
this[actionName](e);
|
|
47
|
-
}
|
|
48
|
-
// 2. 없으면 전역 window에서 확인
|
|
49
|
-
else if (typeof window[actionName] === 'function') {
|
|
50
|
-
window[actionName](e);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}); */
|
|
54
28
|
}
|
|
55
29
|
}
|
|
56
30
|
|
package/src/nx/nxEditor.js
CHANGED
|
@@ -75,7 +75,7 @@ class nxEditor extends nxDiv {
|
|
|
75
75
|
|
|
76
76
|
<div class="menu-bar">
|
|
77
77
|
<button type="button" data-cmd="bold" title="굵게 (Ctrl+B)"><b>B</b></button>
|
|
78
|
-
<button type="button" data-cmd="italic" title="기울임 (Ctrl+I)"><
|
|
78
|
+
<button type="button" data-cmd="italic" title="기울임 (Ctrl+I)"><em>I</em></button>
|
|
79
79
|
<button type="button" data-cmd="underline" title="밑줄 (Ctrl+U)"><u>U</u></button>
|
|
80
80
|
<button type="button" data-cmd="strike" title="취소선"><s>S</s></button>
|
|
81
81
|
|
|
@@ -96,8 +96,8 @@ class nxEditor extends nxDiv {
|
|
|
96
96
|
<button type="button" data-align="center" title="가운데 정렬"><i class="icon-center"></i></button>
|
|
97
97
|
<button type="button" data-align="right" title="오른쪽 정렬"><i class="icon-right"></i></button>
|
|
98
98
|
|
|
99
|
-
<button type="button" data-cmd="bulletList" title="글머리 기호"><i class="icon-
|
|
100
|
-
<button type="button" data-cmd="orderedList" title="번호 매기기"><i class="icon-
|
|
99
|
+
<button type="button" data-cmd="bulletList" title="글머리 기호"><i class="icon-ul"></i></button>
|
|
100
|
+
<button type="button" data-cmd="orderedList" title="번호 매기기"><i class="icon-ol"></i></button>
|
|
101
101
|
|
|
102
102
|
<button type="button" id="img-btn" title="이미지 삽입"><i class="icon-image"></i></button>
|
|
103
103
|
<button type="button" data-cmd="undo" title="실행 취소(Ctrl+Z)"><i class="icon-undo"></i></button>
|