ninegrid2 6.1257.0 → 6.1258.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 +50 -35
- package/dist/bundle.esm.js +50 -35
- package/dist/nx/_nxDiv.js +50 -35
- package/package.json +1 -1
- package/src/nx/_nxDiv.js +50 -35
- package/src/nx/_nxDiv2.js +0 -124
- package/src/nx/nxButtons2.js +0 -29
package/dist/bundle.cjs.js
CHANGED
|
@@ -121838,33 +121838,52 @@ class nxTitle extends HTMLElement {
|
|
|
121838
121838
|
|
|
121839
121839
|
customElements.define("nx-title", nxTitle);
|
|
121840
121840
|
|
|
121841
|
-
class nxDiv extends HTMLElement
|
|
121842
|
-
{
|
|
121841
|
+
class nxDiv extends HTMLElement {
|
|
121843
121842
|
originContents;
|
|
121844
121843
|
#isInitialized = false;
|
|
121844
|
+
#root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
|
|
121845
121845
|
|
|
121846
|
-
constructor
|
|
121846
|
+
constructor() {
|
|
121847
121847
|
super();
|
|
121848
|
-
|
|
121848
|
+
// constructor에서는 속성을 읽을 수 없으므로 초기화만 준비합니다.
|
|
121849
121849
|
}
|
|
121850
121850
|
|
|
121851
121851
|
connectedCallback() {
|
|
121852
121852
|
if (!this.#isInitialized) {
|
|
121853
|
+
// 1. 여기서 속성을 읽어 Shadow DOM 사용 여부를 결정합니다.
|
|
121854
|
+
// use-shadow 속성이 "false"가 아닐 때만 Shadow DOM을 생성 (기본값 true)
|
|
121855
|
+
const useShadow = this.getAttribute("use-shadow") !== "false";
|
|
121856
|
+
|
|
121857
|
+
if (useShadow && !this.shadowRoot) {
|
|
121858
|
+
this.attachShadow({ mode: 'open' });
|
|
121859
|
+
this.#root = this.shadowRoot;
|
|
121860
|
+
} else {
|
|
121861
|
+
this.#root = this;
|
|
121862
|
+
}
|
|
121863
|
+
|
|
121853
121864
|
this.#init();
|
|
121854
|
-
this.#isInitialized = true;
|
|
121865
|
+
this.#isInitialized = true;
|
|
121855
121866
|
return true;
|
|
121856
121867
|
}
|
|
121857
|
-
|
|
121858
121868
|
return false;
|
|
121859
121869
|
}
|
|
121860
121870
|
|
|
121871
|
+
// 자식 클래스에서 접근 가능하도록 getter 제공
|
|
121872
|
+
get root() {
|
|
121873
|
+
return this.#root || this;
|
|
121874
|
+
}
|
|
121875
|
+
|
|
121876
|
+
// 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
|
|
121877
|
+
#getElements() {
|
|
121878
|
+
// ShadowRoot가 있으면 shadowRoot에서, 없으면 본체(this)에서 찾음
|
|
121879
|
+
return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
|
|
121880
|
+
}
|
|
121881
|
+
|
|
121861
121882
|
getData = () => {
|
|
121862
121883
|
const jsonData = {};
|
|
121863
|
-
|
|
121864
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
121865
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
121884
|
+
this.#getElements().forEach(el => {
|
|
121866
121885
|
const key = el.name;
|
|
121867
|
-
if (!key) return;
|
|
121886
|
+
if (!key) return;
|
|
121868
121887
|
|
|
121869
121888
|
let value;
|
|
121870
121889
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -121873,54 +121892,44 @@ class nxDiv extends HTMLElement
|
|
|
121873
121892
|
value = el.value;
|
|
121874
121893
|
}
|
|
121875
121894
|
|
|
121876
|
-
// 중복 name을 대비한 배열 처리
|
|
121877
121895
|
if (jsonData[key]) {
|
|
121878
|
-
if (!Array.isArray(jsonData[key]))
|
|
121879
|
-
jsonData[key] = [jsonData[key]];
|
|
121880
|
-
}
|
|
121896
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
121881
121897
|
jsonData[key].push(value);
|
|
121882
121898
|
} else {
|
|
121883
121899
|
jsonData[key] = value;
|
|
121884
121900
|
}
|
|
121885
121901
|
});
|
|
121886
|
-
|
|
121887
121902
|
return jsonData;
|
|
121888
121903
|
};
|
|
121889
121904
|
|
|
121890
121905
|
setData = (jsonData) => {
|
|
121891
|
-
|
|
121906
|
+
this.#getElements().forEach(el => {
|
|
121892
121907
|
el.removeEventListener("input", this.#changeHandler);
|
|
121893
121908
|
el.addEventListener("input", this.#changeHandler);
|
|
121894
121909
|
});
|
|
121895
121910
|
|
|
121896
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
121897
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
121898
|
-
return;
|
|
121899
|
-
}
|
|
121911
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
121900
121912
|
|
|
121901
121913
|
let bChanged = false;
|
|
121902
|
-
|
|
121914
|
+
this.#getElements().forEach(el => {
|
|
121903
121915
|
const key = el.name;
|
|
121904
121916
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
121905
121917
|
|
|
121906
121918
|
const value = jsonData[key];
|
|
121907
|
-
|
|
121908
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
121909
121919
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
121910
121920
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
121911
|
-
|
|
121912
|
-
el.checked
|
|
121921
|
+
const isChecked = (String(el.value) === String(value));
|
|
121922
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
121923
|
+
el.checked = isChecked;
|
|
121913
121924
|
} else {
|
|
121914
121925
|
if (el.value !== value) bChanged = true;
|
|
121915
121926
|
el.value = value;
|
|
121916
121927
|
}
|
|
121917
121928
|
} else {
|
|
121918
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
121919
121929
|
if (el.textContent !== value) bChanged = true;
|
|
121920
121930
|
el.textContent = value;
|
|
121921
121931
|
}
|
|
121922
121932
|
});
|
|
121923
|
-
|
|
121924
121933
|
if (bChanged) this.#changed(bChanged);
|
|
121925
121934
|
};
|
|
121926
121935
|
|
|
@@ -121942,22 +121951,28 @@ class nxDiv extends HTMLElement
|
|
|
121942
121951
|
}
|
|
121943
121952
|
|
|
121944
121953
|
#init = () => {
|
|
121945
|
-
|
|
121946
|
-
//console.log(this);
|
|
121947
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
121948
|
-
|
|
121949
|
-
/**
|
|
121950
|
-
* css style 적용
|
|
121951
|
-
*/
|
|
121954
|
+
/** CSS style 적용 */
|
|
121952
121955
|
for (const attr of this.attributes) {
|
|
121953
121956
|
if (attr.name.startsWith("css-")) {
|
|
121954
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
121955
121957
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
121956
121958
|
}
|
|
121957
121959
|
}
|
|
121958
121960
|
|
|
121959
121961
|
this.originContents = this.innerHTML.trim();
|
|
121960
121962
|
this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
121963
|
+
|
|
121964
|
+
/**
|
|
121965
|
+
// 2. Shadow DOM을 사용할 때만 내용을 안으로 옮기고 밖을 비웁니다.
|
|
121966
|
+
if (this.shadowRoot) {
|
|
121967
|
+
// 상속받은 자식 클래스(nxButtons 등)가 직접 렌더링하는 경우를 위해
|
|
121968
|
+
// nx-div 태그일 때만 자동으로 내용을 옮겨줍니다.
|
|
121969
|
+
if (this.tagName.toLowerCase() === 'nx-div') {
|
|
121970
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
121971
|
+
}
|
|
121972
|
+
this.innerHTML = "";
|
|
121973
|
+
}
|
|
121974
|
+
// Shadow DOM을 안 쓰면 Light DOM 상태이므로 innerHTML을 유지합니다.
|
|
121975
|
+
*/
|
|
121961
121976
|
};
|
|
121962
121977
|
}
|
|
121963
121978
|
|
package/dist/bundle.esm.js
CHANGED
|
@@ -121834,33 +121834,52 @@ class nxTitle extends HTMLElement {
|
|
|
121834
121834
|
|
|
121835
121835
|
customElements.define("nx-title", nxTitle);
|
|
121836
121836
|
|
|
121837
|
-
class nxDiv extends HTMLElement
|
|
121838
|
-
{
|
|
121837
|
+
class nxDiv extends HTMLElement {
|
|
121839
121838
|
originContents;
|
|
121840
121839
|
#isInitialized = false;
|
|
121840
|
+
#root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
|
|
121841
121841
|
|
|
121842
|
-
constructor
|
|
121842
|
+
constructor() {
|
|
121843
121843
|
super();
|
|
121844
|
-
|
|
121844
|
+
// constructor에서는 속성을 읽을 수 없으므로 초기화만 준비합니다.
|
|
121845
121845
|
}
|
|
121846
121846
|
|
|
121847
121847
|
connectedCallback() {
|
|
121848
121848
|
if (!this.#isInitialized) {
|
|
121849
|
+
// 1. 여기서 속성을 읽어 Shadow DOM 사용 여부를 결정합니다.
|
|
121850
|
+
// use-shadow 속성이 "false"가 아닐 때만 Shadow DOM을 생성 (기본값 true)
|
|
121851
|
+
const useShadow = this.getAttribute("use-shadow") !== "false";
|
|
121852
|
+
|
|
121853
|
+
if (useShadow && !this.shadowRoot) {
|
|
121854
|
+
this.attachShadow({ mode: 'open' });
|
|
121855
|
+
this.#root = this.shadowRoot;
|
|
121856
|
+
} else {
|
|
121857
|
+
this.#root = this;
|
|
121858
|
+
}
|
|
121859
|
+
|
|
121849
121860
|
this.#init();
|
|
121850
|
-
this.#isInitialized = true;
|
|
121861
|
+
this.#isInitialized = true;
|
|
121851
121862
|
return true;
|
|
121852
121863
|
}
|
|
121853
|
-
|
|
121854
121864
|
return false;
|
|
121855
121865
|
}
|
|
121856
121866
|
|
|
121867
|
+
// 자식 클래스에서 접근 가능하도록 getter 제공
|
|
121868
|
+
get root() {
|
|
121869
|
+
return this.#root || this;
|
|
121870
|
+
}
|
|
121871
|
+
|
|
121872
|
+
// 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
|
|
121873
|
+
#getElements() {
|
|
121874
|
+
// ShadowRoot가 있으면 shadowRoot에서, 없으면 본체(this)에서 찾음
|
|
121875
|
+
return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
|
|
121876
|
+
}
|
|
121877
|
+
|
|
121857
121878
|
getData = () => {
|
|
121858
121879
|
const jsonData = {};
|
|
121859
|
-
|
|
121860
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
121861
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
121880
|
+
this.#getElements().forEach(el => {
|
|
121862
121881
|
const key = el.name;
|
|
121863
|
-
if (!key) return;
|
|
121882
|
+
if (!key) return;
|
|
121864
121883
|
|
|
121865
121884
|
let value;
|
|
121866
121885
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -121869,54 +121888,44 @@ class nxDiv extends HTMLElement
|
|
|
121869
121888
|
value = el.value;
|
|
121870
121889
|
}
|
|
121871
121890
|
|
|
121872
|
-
// 중복 name을 대비한 배열 처리
|
|
121873
121891
|
if (jsonData[key]) {
|
|
121874
|
-
if (!Array.isArray(jsonData[key]))
|
|
121875
|
-
jsonData[key] = [jsonData[key]];
|
|
121876
|
-
}
|
|
121892
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
121877
121893
|
jsonData[key].push(value);
|
|
121878
121894
|
} else {
|
|
121879
121895
|
jsonData[key] = value;
|
|
121880
121896
|
}
|
|
121881
121897
|
});
|
|
121882
|
-
|
|
121883
121898
|
return jsonData;
|
|
121884
121899
|
};
|
|
121885
121900
|
|
|
121886
121901
|
setData = (jsonData) => {
|
|
121887
|
-
|
|
121902
|
+
this.#getElements().forEach(el => {
|
|
121888
121903
|
el.removeEventListener("input", this.#changeHandler);
|
|
121889
121904
|
el.addEventListener("input", this.#changeHandler);
|
|
121890
121905
|
});
|
|
121891
121906
|
|
|
121892
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
121893
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
121894
|
-
return;
|
|
121895
|
-
}
|
|
121907
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
121896
121908
|
|
|
121897
121909
|
let bChanged = false;
|
|
121898
|
-
|
|
121910
|
+
this.#getElements().forEach(el => {
|
|
121899
121911
|
const key = el.name;
|
|
121900
121912
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
121901
121913
|
|
|
121902
121914
|
const value = jsonData[key];
|
|
121903
|
-
|
|
121904
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
121905
121915
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
121906
121916
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
121907
|
-
|
|
121908
|
-
el.checked
|
|
121917
|
+
const isChecked = (String(el.value) === String(value));
|
|
121918
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
121919
|
+
el.checked = isChecked;
|
|
121909
121920
|
} else {
|
|
121910
121921
|
if (el.value !== value) bChanged = true;
|
|
121911
121922
|
el.value = value;
|
|
121912
121923
|
}
|
|
121913
121924
|
} else {
|
|
121914
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
121915
121925
|
if (el.textContent !== value) bChanged = true;
|
|
121916
121926
|
el.textContent = value;
|
|
121917
121927
|
}
|
|
121918
121928
|
});
|
|
121919
|
-
|
|
121920
121929
|
if (bChanged) this.#changed(bChanged);
|
|
121921
121930
|
};
|
|
121922
121931
|
|
|
@@ -121938,22 +121947,28 @@ class nxDiv extends HTMLElement
|
|
|
121938
121947
|
}
|
|
121939
121948
|
|
|
121940
121949
|
#init = () => {
|
|
121941
|
-
|
|
121942
|
-
//console.log(this);
|
|
121943
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
121944
|
-
|
|
121945
|
-
/**
|
|
121946
|
-
* css style 적용
|
|
121947
|
-
*/
|
|
121950
|
+
/** CSS style 적용 */
|
|
121948
121951
|
for (const attr of this.attributes) {
|
|
121949
121952
|
if (attr.name.startsWith("css-")) {
|
|
121950
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
121951
121953
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
121952
121954
|
}
|
|
121953
121955
|
}
|
|
121954
121956
|
|
|
121955
121957
|
this.originContents = this.innerHTML.trim();
|
|
121956
121958
|
this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
121959
|
+
|
|
121960
|
+
/**
|
|
121961
|
+
// 2. Shadow DOM을 사용할 때만 내용을 안으로 옮기고 밖을 비웁니다.
|
|
121962
|
+
if (this.shadowRoot) {
|
|
121963
|
+
// 상속받은 자식 클래스(nxButtons 등)가 직접 렌더링하는 경우를 위해
|
|
121964
|
+
// nx-div 태그일 때만 자동으로 내용을 옮겨줍니다.
|
|
121965
|
+
if (this.tagName.toLowerCase() === 'nx-div') {
|
|
121966
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
121967
|
+
}
|
|
121968
|
+
this.innerHTML = "";
|
|
121969
|
+
}
|
|
121970
|
+
// Shadow DOM을 안 쓰면 Light DOM 상태이므로 innerHTML을 유지합니다.
|
|
121971
|
+
*/
|
|
121957
121972
|
};
|
|
121958
121973
|
}
|
|
121959
121974
|
|
package/dist/nx/_nxDiv.js
CHANGED
|
@@ -1,32 +1,51 @@
|
|
|
1
1
|
import ninegrid from "../index.js";
|
|
2
2
|
|
|
3
|
-
export class nxDiv extends HTMLElement
|
|
4
|
-
{
|
|
3
|
+
export class nxDiv 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]", 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,54 +54,44 @@ export class nxDiv 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;
|
|
66
78
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
67
79
|
|
|
68
80
|
const value = jsonData[key];
|
|
69
|
-
|
|
70
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
71
81
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
72
82
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
73
|
-
|
|
74
|
-
el.checked
|
|
83
|
+
const isChecked = (String(el.value) === String(value));
|
|
84
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
85
|
+
el.checked = isChecked;
|
|
75
86
|
} else {
|
|
76
87
|
if (el.value !== value) bChanged = true;
|
|
77
88
|
el.value = value;
|
|
78
89
|
}
|
|
79
90
|
} else {
|
|
80
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
81
91
|
if (el.textContent !== value) bChanged = true;
|
|
82
92
|
el.textContent = value;
|
|
83
93
|
}
|
|
84
94
|
});
|
|
85
|
-
|
|
86
95
|
if (bChanged) this.#changed(bChanged);
|
|
87
96
|
};
|
|
88
97
|
|
|
@@ -104,21 +113,27 @@ export class nxDiv extends HTMLElement
|
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
#init = () => {
|
|
107
|
-
|
|
108
|
-
//console.log(this);
|
|
109
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* css style 적용
|
|
113
|
-
*/
|
|
116
|
+
/** CSS style 적용 */
|
|
114
117
|
for (const attr of this.attributes) {
|
|
115
118
|
if (attr.name.startsWith("css-")) {
|
|
116
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
117
119
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
122
|
|
|
121
123
|
this.originContents = this.innerHTML.trim();
|
|
122
124
|
this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
// 2. Shadow DOM을 사용할 때만 내용을 안으로 옮기고 밖을 비웁니다.
|
|
128
|
+
if (this.shadowRoot) {
|
|
129
|
+
// 상속받은 자식 클래스(nxButtons 등)가 직접 렌더링하는 경우를 위해
|
|
130
|
+
// nx-div 태그일 때만 자동으로 내용을 옮겨줍니다.
|
|
131
|
+
if (this.tagName.toLowerCase() === 'nx-div') {
|
|
132
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
133
|
+
}
|
|
134
|
+
this.innerHTML = "";
|
|
135
|
+
}
|
|
136
|
+
// Shadow DOM을 안 쓰면 Light DOM 상태이므로 innerHTML을 유지합니다.
|
|
137
|
+
*/
|
|
123
138
|
};
|
|
124
139
|
}
|
package/package.json
CHANGED
package/src/nx/_nxDiv.js
CHANGED
|
@@ -1,32 +1,51 @@
|
|
|
1
1
|
import ninegrid from "../index.js";
|
|
2
2
|
|
|
3
|
-
export class nxDiv extends HTMLElement
|
|
4
|
-
{
|
|
3
|
+
export class nxDiv 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]", 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,54 +54,44 @@ export class nxDiv 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;
|
|
66
78
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
67
79
|
|
|
68
80
|
const value = jsonData[key];
|
|
69
|
-
|
|
70
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
71
81
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
72
82
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
73
|
-
|
|
74
|
-
el.checked
|
|
83
|
+
const isChecked = (String(el.value) === String(value));
|
|
84
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
85
|
+
el.checked = isChecked;
|
|
75
86
|
} else {
|
|
76
87
|
if (el.value !== value) bChanged = true;
|
|
77
88
|
el.value = value;
|
|
78
89
|
}
|
|
79
90
|
} else {
|
|
80
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
81
91
|
if (el.textContent !== value) bChanged = true;
|
|
82
92
|
el.textContent = value;
|
|
83
93
|
}
|
|
84
94
|
});
|
|
85
|
-
|
|
86
95
|
if (bChanged) this.#changed(bChanged);
|
|
87
96
|
};
|
|
88
97
|
|
|
@@ -104,21 +113,27 @@ export class nxDiv extends HTMLElement
|
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
#init = () => {
|
|
107
|
-
|
|
108
|
-
//console.log(this);
|
|
109
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* css style 적용
|
|
113
|
-
*/
|
|
116
|
+
/** CSS style 적용 */
|
|
114
117
|
for (const attr of this.attributes) {
|
|
115
118
|
if (attr.name.startsWith("css-")) {
|
|
116
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
117
119
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
122
|
|
|
121
123
|
this.originContents = this.innerHTML.trim();
|
|
122
124
|
this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
// 2. Shadow DOM을 사용할 때만 내용을 안으로 옮기고 밖을 비웁니다.
|
|
128
|
+
if (this.shadowRoot) {
|
|
129
|
+
// 상속받은 자식 클래스(nxButtons 등)가 직접 렌더링하는 경우를 위해
|
|
130
|
+
// nx-div 태그일 때만 자동으로 내용을 옮겨줍니다.
|
|
131
|
+
if (this.tagName.toLowerCase() === 'nx-div') {
|
|
132
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
133
|
+
}
|
|
134
|
+
this.innerHTML = "";
|
|
135
|
+
}
|
|
136
|
+
// Shadow DOM을 안 쓰면 Light DOM 상태이므로 innerHTML을 유지합니다.
|
|
137
|
+
*/
|
|
123
138
|
};
|
|
124
139
|
}
|
package/src/nx/_nxDiv2.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import ninegrid from "../index.js";
|
|
2
|
-
|
|
3
|
-
export class nxDiv2 extends HTMLElement
|
|
4
|
-
{
|
|
5
|
-
originContents;
|
|
6
|
-
#isInitialized = false;
|
|
7
|
-
|
|
8
|
-
constructor () {
|
|
9
|
-
super();
|
|
10
|
-
this.attachShadow({ mode: 'open' });
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
connectedCallback() {
|
|
14
|
-
if (!this.#isInitialized) {
|
|
15
|
-
this.#init();
|
|
16
|
-
this.#isInitialized = true; // 3. 초기화 후 플래그를 true로 변경합니다.
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
getData = () => {
|
|
24
|
-
const jsonData = {};
|
|
25
|
-
|
|
26
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
27
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
28
|
-
const key = el.name;
|
|
29
|
-
if (!key) return; // name이 없는 요소는 건너뜁니다.
|
|
30
|
-
|
|
31
|
-
let value;
|
|
32
|
-
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
33
|
-
value = el.checked;
|
|
34
|
-
} else {
|
|
35
|
-
value = el.value;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// 중복 name을 대비한 배열 처리
|
|
39
|
-
if (jsonData[key]) {
|
|
40
|
-
if (!Array.isArray(jsonData[key])) {
|
|
41
|
-
jsonData[key] = [jsonData[key]];
|
|
42
|
-
}
|
|
43
|
-
jsonData[key].push(value);
|
|
44
|
-
} else {
|
|
45
|
-
jsonData[key] = value;
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
return jsonData;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
setData = (jsonData) => {
|
|
53
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
54
|
-
el.removeEventListener("input", this.#changeHandler);
|
|
55
|
-
el.addEventListener("input", this.#changeHandler);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
if (!jsonData || typeof jsonData !== 'object') {
|
|
59
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
let bChanged = false;
|
|
64
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
65
|
-
const key = el.name;
|
|
66
|
-
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
67
|
-
|
|
68
|
-
const value = jsonData[key];
|
|
69
|
-
|
|
70
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
71
|
-
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
72
|
-
if (el.type === "checkbox" || el.type === "radio") {
|
|
73
|
-
if (el.checked !== (el.value === String(value))) bChanged = true;
|
|
74
|
-
el.checked = (el.value === String(value));
|
|
75
|
-
} else {
|
|
76
|
-
if (el.value !== value) bChanged = true;
|
|
77
|
-
el.value = value;
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
81
|
-
if (el.textContent !== value) bChanged = true;
|
|
82
|
-
el.textContent = value;
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
if (bChanged) this.#changed(bChanged);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
initData = (jsonData) => {
|
|
90
|
-
this.setData(jsonData);
|
|
91
|
-
this.#changed(false);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
#changed = (v) => {
|
|
95
|
-
const parent = this.closest(".detail-wrapper");
|
|
96
|
-
if (parent) {
|
|
97
|
-
const el = parent.querySelector("nx-title2");
|
|
98
|
-
if (el) el.changed = v;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
#changeHandler = (e) => {
|
|
103
|
-
this.#changed(true);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
#init = () => {
|
|
107
|
-
|
|
108
|
-
//console.log(this);
|
|
109
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* css style 적용
|
|
113
|
-
*/
|
|
114
|
-
for (const attr of this.attributes) {
|
|
115
|
-
if (attr.name.startsWith("css-")) {
|
|
116
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
117
|
-
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
this.originContents = this.innerHTML.trim();
|
|
122
|
-
this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
123
|
-
};
|
|
124
|
-
}
|
package/src/nx/nxButtons2.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import ninegrid from "../index.js";
|
|
2
|
-
import {nxDiv} from "./_nxDiv2.js";
|
|
3
|
-
|
|
4
|
-
class nxButtons extends nxDiv2 {
|
|
5
|
-
|
|
6
|
-
constructor() {
|
|
7
|
-
super();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
connectedCallback() {
|
|
11
|
-
if (super.connectedCallback()) this.#init();
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
#init = () => {
|
|
15
|
-
const htmlTmpl = document.createElement("template");
|
|
16
|
-
htmlTmpl.innerHTML = `
|
|
17
|
-
<style>
|
|
18
|
-
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
19
|
-
${ninegrid.getCustomPath(this,"nxButtons.css")}
|
|
20
|
-
</style>
|
|
21
|
-
|
|
22
|
-
${this.originContents}
|
|
23
|
-
`;
|
|
24
|
-
|
|
25
|
-
this.shadowRoot.appendChild(htmlTmpl.content.cloneNode(true));
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
customElements.define("nx-buttons", nxButtons);
|