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.
@@ -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
- this.attachShadow({ mode: 'open' });
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; // 3. 초기화 후 플래그를 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; // name이 없는 요소는 건너뜁니다.
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
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
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
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
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
- if (el.checked !== (el.value === String(value))) bChanged = true;
121912
- el.checked = (el.value === String(value));
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
 
@@ -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
- this.attachShadow({ mode: 'open' });
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; // 3. 초기화 후 플래그를 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; // name이 없는 요소는 건너뜁니다.
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
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
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
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
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
- if (el.checked !== (el.value === String(value))) bChanged = true;
121908
- el.checked = (el.value === String(value));
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
- this.attachShadow({ mode: 'open' });
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; // 3. 초기화 후 플래그를 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; // name이 없는 요소는 건너뜁니다.
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
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
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
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
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
- if (el.checked !== (el.value === String(value))) bChanged = true;
74
- el.checked = (el.value === String(value));
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ninegrid2",
3
3
  "type": "module",
4
- "version": "6.1257.0",
4
+ "version": "6.1258.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
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
- this.attachShadow({ mode: 'open' });
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; // 3. 초기화 후 플래그를 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; // name이 없는 요소는 건너뜁니다.
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
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
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
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
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
- if (el.checked !== (el.value === String(value))) bChanged = true;
74
- el.checked = (el.value === String(value));
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
- }
@@ -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);