ninegrid2 6.1379.0 → 6.1380.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.
@@ -28436,15 +28436,19 @@ customElements.define("nx-title", nxTitle);
28436
28436
  class nxDiv extends HTMLElement {
28437
28437
  originContents;
28438
28438
  #isInitialized = false;
28439
- #root;
28439
+ #root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
28440
28440
 
28441
28441
  constructor() {
28442
28442
  super();
28443
+ // constructor에서는 속성을 읽을 수 없으므로 초기화만 준비합니다.
28443
28444
  }
28444
28445
 
28445
28446
  connectedCallback() {
28446
28447
  if (!this.#isInitialized) {
28448
+ // 1. 여기서 속성을 읽어 Shadow DOM 사용 여부를 결정합니다.
28449
+ // use-shadow 속성이 "false"가 아닐 때만 Shadow DOM을 생성 (기본값 true)
28447
28450
  const useShadow = this.getAttribute("use-shadow") !== "false";
28451
+
28448
28452
  if (useShadow && !this.shadowRoot) {
28449
28453
  this.attachShadow({ mode: 'open' });
28450
28454
  this.#root = this.shadowRoot;
@@ -28454,50 +28458,22 @@ class nxDiv extends HTMLElement {
28454
28458
 
28455
28459
  this.#init();
28456
28460
  this.#isInitialized = true;
28461
+ return true;
28457
28462
  }
28463
+ return false;
28458
28464
  }
28459
28465
 
28460
- get root() { return this.#root || this; }
28466
+ // 자식 클래스에서 접근 가능하도록 getter 제공
28467
+ get root() {
28468
+ return this.#root || this;
28469
+ }
28461
28470
 
28471
+ // 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
28462
28472
  #getElements() {
28473
+ // ShadowRoot가 있으면 shadowRoot에서, 없으면 본체(this)에서 찾음
28463
28474
  return ninegrid.querySelectorAll("input[name], textarea[name], select[name], nx-editor[name]", this.#root);
28464
28475
  }
28465
28476
 
28466
- // [공통 로직 1] 특정 요소에 값을 쓰거나 초기화하는 핵심 함수
28467
- #updateElement(el, value) {
28468
- const tagName = el.tagName.toUpperCase();
28469
- const type = el.type;
28470
- let isChanged = false;
28471
-
28472
- if (["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"].includes(tagName)) {
28473
- if (type === "checkbox") {
28474
- const t = el.getAttribute("true-value") || "Y";
28475
- const isChecked = (String(t) === String(value));
28476
- if (el.checked !== isChecked) isChanged = true;
28477
- el.checked = isChecked;
28478
- } else if (type === "radio") {
28479
- const isChecked = (String(el.value) === String(value));
28480
- if (el.checked !== isChecked) isChanged = true;
28481
- el.checked = isChecked;
28482
- } else {
28483
- if (el.value !== value) isChanged = true;
28484
- el.value = value;
28485
- }
28486
- } else {
28487
- if (el.textContent !== value) isChanged = true;
28488
- el.textContent = value;
28489
- }
28490
- return isChanged;
28491
- }
28492
-
28493
- // [공통 로직 2] 이벤트 리스너 일괄 등록
28494
- #refreshListeners() {
28495
- this.#getElements().forEach(el => {
28496
- el.removeEventListener("input", this.#changeHandler);
28497
- el.addEventListener("input", this.#changeHandler);
28498
- });
28499
- }
28500
-
28501
28477
  getData = () => {
28502
28478
  const jsonData = {};
28503
28479
  this.#getElements().forEach(el => {
@@ -28506,14 +28482,15 @@ class nxDiv extends HTMLElement {
28506
28482
 
28507
28483
  let value;
28508
28484
  if (el.tagName === "INPUT" && el.type === "checkbox") {
28509
- const t = el.getAttribute("true-value") || "Y";
28510
- const f = el.getAttribute("false-value") || "N";
28485
+ let t = el.getAttribute("true-value") || "Y";
28486
+ let f = el.getAttribute("false-value") || "N";
28511
28487
  value = el.checked ? t : f;
28488
+ } else if (el.tagName === "INPUT" && el.type === "radio") {
28489
+ value = el.value;
28512
28490
  } else {
28513
28491
  value = el.value;
28514
28492
  }
28515
28493
 
28516
- // 중복 name 처리 (배열화)
28517
28494
  if (jsonData[key]) {
28518
28495
  if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
28519
28496
  jsonData[key].push(value);
@@ -28524,36 +28501,95 @@ class nxDiv extends HTMLElement {
28524
28501
  return jsonData;
28525
28502
  };
28526
28503
 
28527
- // 파라미터가 있으면 해당 값으로, 없으면 전체 공백 초기화
28528
- clearData = (jsonData = {}) => {
28529
- this.#refreshListeners();
28504
+ clearData = (jsonData) => {
28505
+ this.#getElements().forEach(el => {
28506
+ el.removeEventListener("input", this.#changeHandler);
28507
+ el.addEventListener("input", this.#changeHandler);
28508
+ });
28509
+
28510
+ //if (!jsonData || typeof jsonData !== 'object') return;
28511
+
28512
+ //let bChanged = false;
28530
28513
  this.#getElements().forEach(el => {
28531
28514
  const key = el.name;
28532
- if (!key) return;
28533
- const val = (jsonData && jsonData[key] !== undefined) ? jsonData[key] : "";
28534
- this.#updateElement(el, val);
28515
+ if (!key) return; // name이 없는 요소는 스킵
28516
+ //console.log(el.tagName, key, el.name);
28517
+
28518
+ // 2. jsonData에 해당 key가 없으면 공백("") 할당
28519
+ const value = (jsonData && jsonData[key] !== undefined) ? jsonData[key] : "";
28520
+
28521
+ const tagName = el.tagName.toUpperCase();
28522
+ const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
28523
+
28524
+ if (inputTags.includes(tagName)) {
28525
+ if (el.type === "checkbox") {
28526
+ // 3. true-value 속성을 읽어와서 체크 여부 결정
28527
+ let t = el.getAttribute("true-value") || "Y";
28528
+ el.checked = (String(t) === String(value));
28529
+ } else if (el.type === "radio") {
28530
+ // 라디오 버튼 그룹 내에서 값 일치 여부 확인
28531
+ el.checked = (String(el.value) === String(value));
28532
+ } else {
28533
+ el.value = value;
28534
+ }
28535
+ } else {
28536
+ el.textContent = value;
28537
+ }
28535
28538
  });
28539
+
28536
28540
  this.#changed(false);
28537
28541
  };
28538
28542
 
28539
28543
  setData = (jsonData) => {
28544
+ this.#getElements().forEach(el => {
28545
+ el.removeEventListener("input", this.#changeHandler);
28546
+ el.addEventListener("input", this.#changeHandler);
28547
+ });
28548
+
28540
28549
  if (!jsonData || typeof jsonData !== 'object') return;
28541
- this.#refreshListeners();
28542
28550
 
28543
28551
  let bChanged = false;
28544
28552
  this.#getElements().forEach(el => {
28545
28553
  const key = el.name;
28554
+ //console.log(el.tagName, key, el.name);
28555
+
28546
28556
  if (!key || !jsonData.hasOwnProperty(key)) return;
28547
28557
 
28548
- if (this.#updateElement(el, jsonData[key])) {
28549
- bChanged = true;
28558
+ const value = jsonData[key];
28559
+ const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
28560
+
28561
+ if (inputTags.includes(el.tagName)) {
28562
+ if (el.type === "checkbox") {
28563
+ let t = el.getAttribute("true-value") || "Y";
28564
+ el.getAttribute("false-value") || "N";
28565
+ const isChecked = (t === String(value));
28566
+ if (el.checked !== isChecked) bChanged = true;
28567
+ el.checked = isChecked;
28568
+ } else if (el.type === "radio") {
28569
+ const isChecked = (String(el.value) === String(value));
28570
+ if (el.checked !== isChecked) bChanged = true;
28571
+ // 라디오 버튼 그룹 내에서 값 일치 여부 확인
28572
+ el.checked = isChecked;
28573
+ } else {
28574
+ if (el.value !== value) bChanged = true;
28575
+ el.value = value;
28576
+ }
28577
+ } else {
28578
+ if (el.textContent !== value) bChanged = true;
28579
+ el.textContent = value;
28550
28580
  }
28551
28581
  });
28552
- if (bChanged) this.#changed(true);
28582
+ if (bChanged) this.#changed(bChanged);
28583
+ };
28584
+
28585
+ clearData = (bChanged) => {
28586
+
28587
+
28588
+ this.#changed(false);
28553
28589
  };
28554
28590
 
28555
28591
  initData = (jsonData) => {
28556
- this.clearData(jsonData); // clearData가 이미 초기화 로직을 포함함
28592
+ this.setData(jsonData);
28557
28593
  this.#changed(false);
28558
28594
  };
28559
28595
 
@@ -28565,15 +28601,30 @@ class nxDiv extends HTMLElement {
28565
28601
  }
28566
28602
  }
28567
28603
 
28568
- #changeHandler = (e) => this.#changed(true);
28604
+ #changeHandler = (e) => {
28605
+ this.#changed(true);
28606
+ }
28569
28607
 
28570
28608
  #init = () => {
28609
+ /** CSS style 적용 */
28571
28610
  for (const attr of this.attributes) {
28572
28611
  if (attr.name.startsWith("css-")) {
28573
28612
  this.style.setProperty(attr.name.substring(4), attr.value);
28574
28613
  }
28575
28614
  }
28615
+
28616
+ //console.log("=========");
28617
+ //console.log(this.innerHTML.trim());
28576
28618
  this.originContents = this.innerHTML.trim();
28619
+
28620
+ /**
28621
+ this.originContents = this.innerHTML.trim();
28622
+ this.innerHTML = ""; // 기존 내부 HTML 제거
28623
+
28624
+ // 만약 순수 nx-div로만 쓰일 경우(상속 x), 내용을 shadow에 채워줌
28625
+ if (this.shadowRoot && this.tagName.toLowerCase() === 'nx-div') {
28626
+ this.shadowRoot.innerHTML = this.originContents;
28627
+ } */
28577
28628
  };
28578
28629
  }
28579
28630
 
@@ -28432,15 +28432,19 @@ customElements.define("nx-title", nxTitle);
28432
28432
  class nxDiv extends HTMLElement {
28433
28433
  originContents;
28434
28434
  #isInitialized = false;
28435
- #root;
28435
+ #root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
28436
28436
 
28437
28437
  constructor() {
28438
28438
  super();
28439
+ // constructor에서는 속성을 읽을 수 없으므로 초기화만 준비합니다.
28439
28440
  }
28440
28441
 
28441
28442
  connectedCallback() {
28442
28443
  if (!this.#isInitialized) {
28444
+ // 1. 여기서 속성을 읽어 Shadow DOM 사용 여부를 결정합니다.
28445
+ // use-shadow 속성이 "false"가 아닐 때만 Shadow DOM을 생성 (기본값 true)
28443
28446
  const useShadow = this.getAttribute("use-shadow") !== "false";
28447
+
28444
28448
  if (useShadow && !this.shadowRoot) {
28445
28449
  this.attachShadow({ mode: 'open' });
28446
28450
  this.#root = this.shadowRoot;
@@ -28450,50 +28454,22 @@ class nxDiv extends HTMLElement {
28450
28454
 
28451
28455
  this.#init();
28452
28456
  this.#isInitialized = true;
28457
+ return true;
28453
28458
  }
28459
+ return false;
28454
28460
  }
28455
28461
 
28456
- get root() { return this.#root || this; }
28462
+ // 자식 클래스에서 접근 가능하도록 getter 제공
28463
+ get root() {
28464
+ return this.#root || this;
28465
+ }
28457
28466
 
28467
+ // 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
28458
28468
  #getElements() {
28469
+ // ShadowRoot가 있으면 shadowRoot에서, 없으면 본체(this)에서 찾음
28459
28470
  return ninegrid.querySelectorAll("input[name], textarea[name], select[name], nx-editor[name]", this.#root);
28460
28471
  }
28461
28472
 
28462
- // [공통 로직 1] 특정 요소에 값을 쓰거나 초기화하는 핵심 함수
28463
- #updateElement(el, value) {
28464
- const tagName = el.tagName.toUpperCase();
28465
- const type = el.type;
28466
- let isChanged = false;
28467
-
28468
- if (["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"].includes(tagName)) {
28469
- if (type === "checkbox") {
28470
- const t = el.getAttribute("true-value") || "Y";
28471
- const isChecked = (String(t) === String(value));
28472
- if (el.checked !== isChecked) isChanged = true;
28473
- el.checked = isChecked;
28474
- } else if (type === "radio") {
28475
- const isChecked = (String(el.value) === String(value));
28476
- if (el.checked !== isChecked) isChanged = true;
28477
- el.checked = isChecked;
28478
- } else {
28479
- if (el.value !== value) isChanged = true;
28480
- el.value = value;
28481
- }
28482
- } else {
28483
- if (el.textContent !== value) isChanged = true;
28484
- el.textContent = value;
28485
- }
28486
- return isChanged;
28487
- }
28488
-
28489
- // [공통 로직 2] 이벤트 리스너 일괄 등록
28490
- #refreshListeners() {
28491
- this.#getElements().forEach(el => {
28492
- el.removeEventListener("input", this.#changeHandler);
28493
- el.addEventListener("input", this.#changeHandler);
28494
- });
28495
- }
28496
-
28497
28473
  getData = () => {
28498
28474
  const jsonData = {};
28499
28475
  this.#getElements().forEach(el => {
@@ -28502,14 +28478,15 @@ class nxDiv extends HTMLElement {
28502
28478
 
28503
28479
  let value;
28504
28480
  if (el.tagName === "INPUT" && el.type === "checkbox") {
28505
- const t = el.getAttribute("true-value") || "Y";
28506
- const f = el.getAttribute("false-value") || "N";
28481
+ let t = el.getAttribute("true-value") || "Y";
28482
+ let f = el.getAttribute("false-value") || "N";
28507
28483
  value = el.checked ? t : f;
28484
+ } else if (el.tagName === "INPUT" && el.type === "radio") {
28485
+ value = el.value;
28508
28486
  } else {
28509
28487
  value = el.value;
28510
28488
  }
28511
28489
 
28512
- // 중복 name 처리 (배열화)
28513
28490
  if (jsonData[key]) {
28514
28491
  if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
28515
28492
  jsonData[key].push(value);
@@ -28520,36 +28497,95 @@ class nxDiv extends HTMLElement {
28520
28497
  return jsonData;
28521
28498
  };
28522
28499
 
28523
- // 파라미터가 있으면 해당 값으로, 없으면 전체 공백 초기화
28524
- clearData = (jsonData = {}) => {
28525
- this.#refreshListeners();
28500
+ clearData = (jsonData) => {
28501
+ this.#getElements().forEach(el => {
28502
+ el.removeEventListener("input", this.#changeHandler);
28503
+ el.addEventListener("input", this.#changeHandler);
28504
+ });
28505
+
28506
+ //if (!jsonData || typeof jsonData !== 'object') return;
28507
+
28508
+ //let bChanged = false;
28526
28509
  this.#getElements().forEach(el => {
28527
28510
  const key = el.name;
28528
- if (!key) return;
28529
- const val = (jsonData && jsonData[key] !== undefined) ? jsonData[key] : "";
28530
- this.#updateElement(el, val);
28511
+ if (!key) return; // name이 없는 요소는 스킵
28512
+ //console.log(el.tagName, key, el.name);
28513
+
28514
+ // 2. jsonData에 해당 key가 없으면 공백("") 할당
28515
+ const value = (jsonData && jsonData[key] !== undefined) ? jsonData[key] : "";
28516
+
28517
+ const tagName = el.tagName.toUpperCase();
28518
+ const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
28519
+
28520
+ if (inputTags.includes(tagName)) {
28521
+ if (el.type === "checkbox") {
28522
+ // 3. true-value 속성을 읽어와서 체크 여부 결정
28523
+ let t = el.getAttribute("true-value") || "Y";
28524
+ el.checked = (String(t) === String(value));
28525
+ } else if (el.type === "radio") {
28526
+ // 라디오 버튼 그룹 내에서 값 일치 여부 확인
28527
+ el.checked = (String(el.value) === String(value));
28528
+ } else {
28529
+ el.value = value;
28530
+ }
28531
+ } else {
28532
+ el.textContent = value;
28533
+ }
28531
28534
  });
28535
+
28532
28536
  this.#changed(false);
28533
28537
  };
28534
28538
 
28535
28539
  setData = (jsonData) => {
28540
+ this.#getElements().forEach(el => {
28541
+ el.removeEventListener("input", this.#changeHandler);
28542
+ el.addEventListener("input", this.#changeHandler);
28543
+ });
28544
+
28536
28545
  if (!jsonData || typeof jsonData !== 'object') return;
28537
- this.#refreshListeners();
28538
28546
 
28539
28547
  let bChanged = false;
28540
28548
  this.#getElements().forEach(el => {
28541
28549
  const key = el.name;
28550
+ //console.log(el.tagName, key, el.name);
28551
+
28542
28552
  if (!key || !jsonData.hasOwnProperty(key)) return;
28543
28553
 
28544
- if (this.#updateElement(el, jsonData[key])) {
28545
- bChanged = true;
28554
+ const value = jsonData[key];
28555
+ const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
28556
+
28557
+ if (inputTags.includes(el.tagName)) {
28558
+ if (el.type === "checkbox") {
28559
+ let t = el.getAttribute("true-value") || "Y";
28560
+ el.getAttribute("false-value") || "N";
28561
+ const isChecked = (t === String(value));
28562
+ if (el.checked !== isChecked) bChanged = true;
28563
+ el.checked = isChecked;
28564
+ } else if (el.type === "radio") {
28565
+ const isChecked = (String(el.value) === String(value));
28566
+ if (el.checked !== isChecked) bChanged = true;
28567
+ // 라디오 버튼 그룹 내에서 값 일치 여부 확인
28568
+ el.checked = isChecked;
28569
+ } else {
28570
+ if (el.value !== value) bChanged = true;
28571
+ el.value = value;
28572
+ }
28573
+ } else {
28574
+ if (el.textContent !== value) bChanged = true;
28575
+ el.textContent = value;
28546
28576
  }
28547
28577
  });
28548
- if (bChanged) this.#changed(true);
28578
+ if (bChanged) this.#changed(bChanged);
28579
+ };
28580
+
28581
+ clearData = (bChanged) => {
28582
+
28583
+
28584
+ this.#changed(false);
28549
28585
  };
28550
28586
 
28551
28587
  initData = (jsonData) => {
28552
- this.clearData(jsonData); // clearData가 이미 초기화 로직을 포함함
28588
+ this.setData(jsonData);
28553
28589
  this.#changed(false);
28554
28590
  };
28555
28591
 
@@ -28561,15 +28597,30 @@ class nxDiv extends HTMLElement {
28561
28597
  }
28562
28598
  }
28563
28599
 
28564
- #changeHandler = (e) => this.#changed(true);
28600
+ #changeHandler = (e) => {
28601
+ this.#changed(true);
28602
+ }
28565
28603
 
28566
28604
  #init = () => {
28605
+ /** CSS style 적용 */
28567
28606
  for (const attr of this.attributes) {
28568
28607
  if (attr.name.startsWith("css-")) {
28569
28608
  this.style.setProperty(attr.name.substring(4), attr.value);
28570
28609
  }
28571
28610
  }
28611
+
28612
+ //console.log("=========");
28613
+ //console.log(this.innerHTML.trim());
28572
28614
  this.originContents = this.innerHTML.trim();
28615
+
28616
+ /**
28617
+ this.originContents = this.innerHTML.trim();
28618
+ this.innerHTML = ""; // 기존 내부 HTML 제거
28619
+
28620
+ // 만약 순수 nx-div로만 쓰일 경우(상속 x), 내용을 shadow에 채워줌
28621
+ if (this.shadowRoot && this.tagName.toLowerCase() === 'nx-div') {
28622
+ this.shadowRoot.innerHTML = this.originContents;
28623
+ } */
28573
28624
  };
28574
28625
  }
28575
28626
 
package/dist/nx/_nxDiv.js CHANGED
@@ -3,15 +3,19 @@ import ninegrid from "../index.js";
3
3
  export class nxDiv extends HTMLElement {
4
4
  originContents;
5
5
  #isInitialized = false;
6
- #root;
6
+ #root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
7
7
 
8
8
  constructor() {
9
9
  super();
10
+ // constructor에서는 속성을 읽을 수 없으므로 초기화만 준비합니다.
10
11
  }
11
12
 
12
13
  connectedCallback() {
13
14
  if (!this.#isInitialized) {
15
+ // 1. 여기서 속성을 읽어 Shadow DOM 사용 여부를 결정합니다.
16
+ // use-shadow 속성이 "false"가 아닐 때만 Shadow DOM을 생성 (기본값 true)
14
17
  const useShadow = this.getAttribute("use-shadow") !== "false";
18
+
15
19
  if (useShadow && !this.shadowRoot) {
16
20
  this.attachShadow({ mode: 'open' });
17
21
  this.#root = this.shadowRoot;
@@ -21,50 +25,22 @@ export class nxDiv extends HTMLElement {
21
25
 
22
26
  this.#init();
23
27
  this.#isInitialized = true;
28
+ return true;
24
29
  }
30
+ return false;
25
31
  }
26
32
 
27
- get root() { return this.#root || this; }
33
+ // 자식 클래스에서 접근 가능하도록 getter 제공
34
+ get root() {
35
+ return this.#root || this;
36
+ }
28
37
 
38
+ // 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
29
39
  #getElements() {
40
+ // ShadowRoot가 있으면 shadowRoot에서, 없으면 본체(this)에서 찾음
30
41
  return ninegrid.querySelectorAll("input[name], textarea[name], select[name], nx-editor[name]", this.#root);
31
42
  }
32
43
 
33
- // [공통 로직 1] 특정 요소에 값을 쓰거나 초기화하는 핵심 함수
34
- #updateElement(el, value) {
35
- const tagName = el.tagName.toUpperCase();
36
- const type = el.type;
37
- let isChanged = false;
38
-
39
- if (["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"].includes(tagName)) {
40
- if (type === "checkbox") {
41
- const t = el.getAttribute("true-value") || "Y";
42
- const isChecked = (String(t) === String(value));
43
- if (el.checked !== isChecked) isChanged = true;
44
- el.checked = isChecked;
45
- } else if (type === "radio") {
46
- const isChecked = (String(el.value) === String(value));
47
- if (el.checked !== isChecked) isChanged = true;
48
- el.checked = isChecked;
49
- } else {
50
- if (el.value !== value) isChanged = true;
51
- el.value = value;
52
- }
53
- } else {
54
- if (el.textContent !== value) isChanged = true;
55
- el.textContent = value;
56
- }
57
- return isChanged;
58
- }
59
-
60
- // [공통 로직 2] 이벤트 리스너 일괄 등록
61
- #refreshListeners() {
62
- this.#getElements().forEach(el => {
63
- el.removeEventListener("input", this.#changeHandler);
64
- el.addEventListener("input", this.#changeHandler);
65
- });
66
- }
67
-
68
44
  getData = () => {
69
45
  const jsonData = {};
70
46
  this.#getElements().forEach(el => {
@@ -73,14 +49,15 @@ export class nxDiv extends HTMLElement {
73
49
 
74
50
  let value;
75
51
  if (el.tagName === "INPUT" && el.type === "checkbox") {
76
- const t = el.getAttribute("true-value") || "Y";
77
- const f = el.getAttribute("false-value") || "N";
52
+ let t = el.getAttribute("true-value") || "Y";
53
+ let f = el.getAttribute("false-value") || "N";
78
54
  value = el.checked ? t : f;
55
+ } else if (el.tagName === "INPUT" && el.type === "radio") {
56
+ value = el.value;
79
57
  } else {
80
58
  value = el.value;
81
59
  }
82
60
 
83
- // 중복 name 처리 (배열화)
84
61
  if (jsonData[key]) {
85
62
  if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
86
63
  jsonData[key].push(value);
@@ -91,36 +68,95 @@ export class nxDiv extends HTMLElement {
91
68
  return jsonData;
92
69
  };
93
70
 
94
- // 파라미터가 있으면 해당 값으로, 없으면 전체 공백 초기화
95
- clearData = (jsonData = {}) => {
96
- this.#refreshListeners();
71
+ clearData = (jsonData) => {
72
+ this.#getElements().forEach(el => {
73
+ el.removeEventListener("input", this.#changeHandler);
74
+ el.addEventListener("input", this.#changeHandler);
75
+ });
76
+
77
+ //if (!jsonData || typeof jsonData !== 'object') return;
78
+
79
+ //let bChanged = false;
97
80
  this.#getElements().forEach(el => {
98
81
  const key = el.name;
99
- if (!key) return;
100
- const val = (jsonData && jsonData[key] !== undefined) ? jsonData[key] : "";
101
- this.#updateElement(el, val);
82
+ if (!key) return; // name이 없는 요소는 스킵
83
+ //console.log(el.tagName, key, el.name);
84
+
85
+ // 2. jsonData에 해당 key가 없으면 공백("") 할당
86
+ const value = (jsonData && jsonData[key] !== undefined) ? jsonData[key] : "";
87
+
88
+ const tagName = el.tagName.toUpperCase();
89
+ const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
90
+
91
+ if (inputTags.includes(tagName)) {
92
+ if (el.type === "checkbox") {
93
+ // 3. true-value 속성을 읽어와서 체크 여부 결정
94
+ let t = el.getAttribute("true-value") || "Y";
95
+ el.checked = (String(t) === String(value));
96
+ } else if (el.type === "radio") {
97
+ // 라디오 버튼 그룹 내에서 값 일치 여부 확인
98
+ el.checked = (String(el.value) === String(value));
99
+ } else {
100
+ el.value = value;
101
+ }
102
+ } else {
103
+ el.textContent = value;
104
+ }
102
105
  });
106
+
103
107
  this.#changed(false);
104
108
  };
105
109
 
106
110
  setData = (jsonData) => {
111
+ this.#getElements().forEach(el => {
112
+ el.removeEventListener("input", this.#changeHandler);
113
+ el.addEventListener("input", this.#changeHandler);
114
+ });
115
+
107
116
  if (!jsonData || typeof jsonData !== 'object') return;
108
- this.#refreshListeners();
109
117
 
110
118
  let bChanged = false;
111
119
  this.#getElements().forEach(el => {
112
120
  const key = el.name;
121
+ //console.log(el.tagName, key, el.name);
122
+
113
123
  if (!key || !jsonData.hasOwnProperty(key)) return;
114
124
 
115
- if (this.#updateElement(el, jsonData[key])) {
116
- bChanged = true;
125
+ const value = jsonData[key];
126
+ const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
127
+
128
+ if (inputTags.includes(el.tagName)) {
129
+ if (el.type === "checkbox") {
130
+ let t = el.getAttribute("true-value") || "Y";
131
+ let f = el.getAttribute("false-value") || "N";
132
+ const isChecked = (t === String(value));
133
+ if (el.checked !== isChecked) bChanged = true;
134
+ el.checked = isChecked;
135
+ } else if (el.type === "radio") {
136
+ const isChecked = (String(el.value) === String(value));
137
+ if (el.checked !== isChecked) bChanged = true;
138
+ // 라디오 버튼 그룹 내에서 값 일치 여부 확인
139
+ el.checked = isChecked;
140
+ } else {
141
+ if (el.value !== value) bChanged = true;
142
+ el.value = value;
143
+ }
144
+ } else {
145
+ if (el.textContent !== value) bChanged = true;
146
+ el.textContent = value;
117
147
  }
118
148
  });
119
- if (bChanged) this.#changed(true);
149
+ if (bChanged) this.#changed(bChanged);
150
+ };
151
+
152
+ clearData = (bChanged) => {
153
+
154
+
155
+ this.#changed(false);
120
156
  };
121
157
 
122
158
  initData = (jsonData) => {
123
- this.clearData(jsonData); // clearData가 이미 초기화 로직을 포함함
159
+ this.setData(jsonData);
124
160
  this.#changed(false);
125
161
  };
126
162
 
@@ -132,14 +168,29 @@ export class nxDiv extends HTMLElement {
132
168
  }
133
169
  }
134
170
 
135
- #changeHandler = (e) => this.#changed(true);
171
+ #changeHandler = (e) => {
172
+ this.#changed(true);
173
+ }
136
174
 
137
175
  #init = () => {
176
+ /** CSS style 적용 */
138
177
  for (const attr of this.attributes) {
139
178
  if (attr.name.startsWith("css-")) {
140
179
  this.style.setProperty(attr.name.substring(4), attr.value);
141
180
  }
142
181
  }
182
+
183
+ //console.log("=========");
184
+ //console.log(this.innerHTML.trim());
143
185
  this.originContents = this.innerHTML.trim();
186
+
187
+ /**
188
+ this.originContents = this.innerHTML.trim();
189
+ this.innerHTML = ""; // 기존 내부 HTML 제거
190
+
191
+ // 만약 순수 nx-div로만 쓰일 경우(상속 x), 내용을 shadow에 채워줌
192
+ if (this.shadowRoot && this.tagName.toLowerCase() === 'nx-div') {
193
+ this.shadowRoot.innerHTML = this.originContents;
194
+ } */
144
195
  };
145
196
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ninegrid2",
3
3
  "type": "module",
4
- "version": "6.1379.0",
4
+ "version": "6.1380.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
package/src/nx/_nxDiv.js CHANGED
@@ -3,15 +3,19 @@ import ninegrid from "../index.js";
3
3
  export class nxDiv extends HTMLElement {
4
4
  originContents;
5
5
  #isInitialized = false;
6
- #root;
6
+ #root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
7
7
 
8
8
  constructor() {
9
9
  super();
10
+ // constructor에서는 속성을 읽을 수 없으므로 초기화만 준비합니다.
10
11
  }
11
12
 
12
13
  connectedCallback() {
13
14
  if (!this.#isInitialized) {
15
+ // 1. 여기서 속성을 읽어 Shadow DOM 사용 여부를 결정합니다.
16
+ // use-shadow 속성이 "false"가 아닐 때만 Shadow DOM을 생성 (기본값 true)
14
17
  const useShadow = this.getAttribute("use-shadow") !== "false";
18
+
15
19
  if (useShadow && !this.shadowRoot) {
16
20
  this.attachShadow({ mode: 'open' });
17
21
  this.#root = this.shadowRoot;
@@ -21,50 +25,22 @@ export class nxDiv extends HTMLElement {
21
25
 
22
26
  this.#init();
23
27
  this.#isInitialized = true;
28
+ return true;
24
29
  }
30
+ return false;
25
31
  }
26
32
 
27
- get root() { return this.#root || this; }
33
+ // 자식 클래스에서 접근 가능하도록 getter 제공
34
+ get root() {
35
+ return this.#root || this;
36
+ }
28
37
 
38
+ // 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
29
39
  #getElements() {
40
+ // ShadowRoot가 있으면 shadowRoot에서, 없으면 본체(this)에서 찾음
30
41
  return ninegrid.querySelectorAll("input[name], textarea[name], select[name], nx-editor[name]", this.#root);
31
42
  }
32
43
 
33
- // [공통 로직 1] 특정 요소에 값을 쓰거나 초기화하는 핵심 함수
34
- #updateElement(el, value) {
35
- const tagName = el.tagName.toUpperCase();
36
- const type = el.type;
37
- let isChanged = false;
38
-
39
- if (["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"].includes(tagName)) {
40
- if (type === "checkbox") {
41
- const t = el.getAttribute("true-value") || "Y";
42
- const isChecked = (String(t) === String(value));
43
- if (el.checked !== isChecked) isChanged = true;
44
- el.checked = isChecked;
45
- } else if (type === "radio") {
46
- const isChecked = (String(el.value) === String(value));
47
- if (el.checked !== isChecked) isChanged = true;
48
- el.checked = isChecked;
49
- } else {
50
- if (el.value !== value) isChanged = true;
51
- el.value = value;
52
- }
53
- } else {
54
- if (el.textContent !== value) isChanged = true;
55
- el.textContent = value;
56
- }
57
- return isChanged;
58
- }
59
-
60
- // [공통 로직 2] 이벤트 리스너 일괄 등록
61
- #refreshListeners() {
62
- this.#getElements().forEach(el => {
63
- el.removeEventListener("input", this.#changeHandler);
64
- el.addEventListener("input", this.#changeHandler);
65
- });
66
- }
67
-
68
44
  getData = () => {
69
45
  const jsonData = {};
70
46
  this.#getElements().forEach(el => {
@@ -73,14 +49,15 @@ export class nxDiv extends HTMLElement {
73
49
 
74
50
  let value;
75
51
  if (el.tagName === "INPUT" && el.type === "checkbox") {
76
- const t = el.getAttribute("true-value") || "Y";
77
- const f = el.getAttribute("false-value") || "N";
52
+ let t = el.getAttribute("true-value") || "Y";
53
+ let f = el.getAttribute("false-value") || "N";
78
54
  value = el.checked ? t : f;
55
+ } else if (el.tagName === "INPUT" && el.type === "radio") {
56
+ value = el.value;
79
57
  } else {
80
58
  value = el.value;
81
59
  }
82
60
 
83
- // 중복 name 처리 (배열화)
84
61
  if (jsonData[key]) {
85
62
  if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
86
63
  jsonData[key].push(value);
@@ -91,36 +68,95 @@ export class nxDiv extends HTMLElement {
91
68
  return jsonData;
92
69
  };
93
70
 
94
- // 파라미터가 있으면 해당 값으로, 없으면 전체 공백 초기화
95
- clearData = (jsonData = {}) => {
96
- this.#refreshListeners();
71
+ clearData = (jsonData) => {
72
+ this.#getElements().forEach(el => {
73
+ el.removeEventListener("input", this.#changeHandler);
74
+ el.addEventListener("input", this.#changeHandler);
75
+ });
76
+
77
+ //if (!jsonData || typeof jsonData !== 'object') return;
78
+
79
+ //let bChanged = false;
97
80
  this.#getElements().forEach(el => {
98
81
  const key = el.name;
99
- if (!key) return;
100
- const val = (jsonData && jsonData[key] !== undefined) ? jsonData[key] : "";
101
- this.#updateElement(el, val);
82
+ if (!key) return; // name이 없는 요소는 스킵
83
+ //console.log(el.tagName, key, el.name);
84
+
85
+ // 2. jsonData에 해당 key가 없으면 공백("") 할당
86
+ const value = (jsonData && jsonData[key] !== undefined) ? jsonData[key] : "";
87
+
88
+ const tagName = el.tagName.toUpperCase();
89
+ const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
90
+
91
+ if (inputTags.includes(tagName)) {
92
+ if (el.type === "checkbox") {
93
+ // 3. true-value 속성을 읽어와서 체크 여부 결정
94
+ let t = el.getAttribute("true-value") || "Y";
95
+ el.checked = (String(t) === String(value));
96
+ } else if (el.type === "radio") {
97
+ // 라디오 버튼 그룹 내에서 값 일치 여부 확인
98
+ el.checked = (String(el.value) === String(value));
99
+ } else {
100
+ el.value = value;
101
+ }
102
+ } else {
103
+ el.textContent = value;
104
+ }
102
105
  });
106
+
103
107
  this.#changed(false);
104
108
  };
105
109
 
106
110
  setData = (jsonData) => {
111
+ this.#getElements().forEach(el => {
112
+ el.removeEventListener("input", this.#changeHandler);
113
+ el.addEventListener("input", this.#changeHandler);
114
+ });
115
+
107
116
  if (!jsonData || typeof jsonData !== 'object') return;
108
- this.#refreshListeners();
109
117
 
110
118
  let bChanged = false;
111
119
  this.#getElements().forEach(el => {
112
120
  const key = el.name;
121
+ //console.log(el.tagName, key, el.name);
122
+
113
123
  if (!key || !jsonData.hasOwnProperty(key)) return;
114
124
 
115
- if (this.#updateElement(el, jsonData[key])) {
116
- bChanged = true;
125
+ const value = jsonData[key];
126
+ const inputTags = ["INPUT", "TEXTAREA", "SELECT", "NX-EDITOR"];
127
+
128
+ if (inputTags.includes(el.tagName)) {
129
+ if (el.type === "checkbox") {
130
+ let t = el.getAttribute("true-value") || "Y";
131
+ let f = el.getAttribute("false-value") || "N";
132
+ const isChecked = (t === String(value));
133
+ if (el.checked !== isChecked) bChanged = true;
134
+ el.checked = isChecked;
135
+ } else if (el.type === "radio") {
136
+ const isChecked = (String(el.value) === String(value));
137
+ if (el.checked !== isChecked) bChanged = true;
138
+ // 라디오 버튼 그룹 내에서 값 일치 여부 확인
139
+ el.checked = isChecked;
140
+ } else {
141
+ if (el.value !== value) bChanged = true;
142
+ el.value = value;
143
+ }
144
+ } else {
145
+ if (el.textContent !== value) bChanged = true;
146
+ el.textContent = value;
117
147
  }
118
148
  });
119
- if (bChanged) this.#changed(true);
149
+ if (bChanged) this.#changed(bChanged);
150
+ };
151
+
152
+ clearData = (bChanged) => {
153
+
154
+
155
+ this.#changed(false);
120
156
  };
121
157
 
122
158
  initData = (jsonData) => {
123
- this.clearData(jsonData); // clearData가 이미 초기화 로직을 포함함
159
+ this.setData(jsonData);
124
160
  this.#changed(false);
125
161
  };
126
162
 
@@ -132,14 +168,29 @@ export class nxDiv extends HTMLElement {
132
168
  }
133
169
  }
134
170
 
135
- #changeHandler = (e) => this.#changed(true);
171
+ #changeHandler = (e) => {
172
+ this.#changed(true);
173
+ }
136
174
 
137
175
  #init = () => {
176
+ /** CSS style 적용 */
138
177
  for (const attr of this.attributes) {
139
178
  if (attr.name.startsWith("css-")) {
140
179
  this.style.setProperty(attr.name.substring(4), attr.value);
141
180
  }
142
181
  }
182
+
183
+ //console.log("=========");
184
+ //console.log(this.innerHTML.trim());
143
185
  this.originContents = this.innerHTML.trim();
186
+
187
+ /**
188
+ this.originContents = this.innerHTML.trim();
189
+ this.innerHTML = ""; // 기존 내부 HTML 제거
190
+
191
+ // 만약 순수 nx-div로만 쓰일 경우(상속 x), 내용을 shadow에 채워줌
192
+ if (this.shadowRoot && this.tagName.toLowerCase() === 'nx-div') {
193
+ this.shadowRoot.innerHTML = this.originContents;
194
+ } */
144
195
  };
145
196
  }