ninegrid2 6.1249.0 → 6.1250.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 +63 -49
- package/dist/bundle.esm.js +63 -49
- package/dist/nx/_nxDiv.js +42 -37
- package/dist/nx/_nxDiv.js.bak2 +125 -0
- package/dist/nx/nxButtons.js +23 -14
- package/dist/nx/nxButtons.js.bak +29 -0
- package/package.json +1 -1
- package/src/nx/_nxDiv.js +42 -37
- package/src/nx/_nxDiv.js.bak2 +125 -0
- package/src/nx/nxButtons.js +23 -14
- package/src/nx/nxButtons.js.bak +29 -0
package/dist/bundle.cjs.js
CHANGED
|
@@ -121838,33 +121838,48 @@ 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
|
+
// 1. 'use-shadow' 속성이 "false"가 아니면 기본적으로 Shadow DOM을 사용하도록 설정
|
|
121849
|
+
const useShadow = this.getAttribute("use-shadow") !== "false";
|
|
121850
|
+
|
|
121851
|
+
if (useShadow) {
|
|
121852
|
+
this.attachShadow({ mode: 'open' });
|
|
121853
|
+
this.#root = this.shadowRoot;
|
|
121854
|
+
} else {
|
|
121855
|
+
this.#root = this;
|
|
121856
|
+
}
|
|
121849
121857
|
}
|
|
121850
|
-
|
|
121858
|
+
|
|
121851
121859
|
connectedCallback() {
|
|
121852
121860
|
if (!this.#isInitialized) {
|
|
121853
121861
|
this.#init();
|
|
121854
|
-
this.#isInitialized = true;
|
|
121862
|
+
this.#isInitialized = true;
|
|
121855
121863
|
return true;
|
|
121856
121864
|
}
|
|
121857
|
-
|
|
121858
121865
|
return false;
|
|
121859
121866
|
}
|
|
121860
121867
|
|
|
121868
|
+
// 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
|
|
121869
|
+
#getElements() {
|
|
121870
|
+
return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
|
|
121871
|
+
}
|
|
121872
|
+
|
|
121873
|
+
// 자식 클래스에서 접근할 수 있도록 getter 제공
|
|
121874
|
+
get root() {
|
|
121875
|
+
return this.#root;
|
|
121876
|
+
}
|
|
121877
|
+
|
|
121861
121878
|
getData = () => {
|
|
121862
121879
|
const jsonData = {};
|
|
121863
|
-
|
|
121864
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
121865
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
121880
|
+
this.#getElements().forEach(el => {
|
|
121866
121881
|
const key = el.name;
|
|
121867
|
-
if (!key) return;
|
|
121882
|
+
if (!key) return;
|
|
121868
121883
|
|
|
121869
121884
|
let value;
|
|
121870
121885
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -121873,50 +121888,40 @@ class nxDiv extends HTMLElement
|
|
|
121873
121888
|
value = el.value;
|
|
121874
121889
|
}
|
|
121875
121890
|
|
|
121876
|
-
// 중복 name을 대비한 배열 처리
|
|
121877
121891
|
if (jsonData[key]) {
|
|
121878
|
-
if (!Array.isArray(jsonData[key]))
|
|
121879
|
-
jsonData[key] = [jsonData[key]];
|
|
121880
|
-
}
|
|
121892
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
121881
121893
|
jsonData[key].push(value);
|
|
121882
121894
|
} else {
|
|
121883
121895
|
jsonData[key] = value;
|
|
121884
121896
|
}
|
|
121885
121897
|
});
|
|
121886
|
-
|
|
121887
121898
|
return jsonData;
|
|
121888
121899
|
};
|
|
121889
121900
|
|
|
121890
121901
|
setData = (jsonData) => {
|
|
121891
|
-
|
|
121892
|
-
console.log("------", el);
|
|
121902
|
+
this.#getElements().forEach(el => {
|
|
121893
121903
|
el.removeEventListener("input", this.#changeHandler);
|
|
121894
121904
|
el.addEventListener("input", this.#changeHandler);
|
|
121895
121905
|
});
|
|
121896
121906
|
|
|
121897
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
121898
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
121899
|
-
return;
|
|
121900
|
-
}
|
|
121907
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
121901
121908
|
|
|
121902
121909
|
let bChanged = false;
|
|
121903
|
-
|
|
121910
|
+
this.#getElements().forEach(el => {
|
|
121904
121911
|
const key = el.name;
|
|
121905
121912
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
121906
121913
|
|
|
121907
121914
|
const value = jsonData[key];
|
|
121908
|
-
|
|
121909
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
121910
121915
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
121911
121916
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
121912
|
-
|
|
121913
|
-
el.checked
|
|
121917
|
+
const isChecked = (String(el.value) === String(value));
|
|
121918
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
121919
|
+
el.checked = isChecked;
|
|
121914
121920
|
} else {
|
|
121915
121921
|
if (el.value !== value) bChanged = true;
|
|
121916
121922
|
el.value = value;
|
|
121917
121923
|
}
|
|
121918
121924
|
} else {
|
|
121919
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
121920
121925
|
if (el.textContent !== value) bChanged = true;
|
|
121921
121926
|
el.textContent = value;
|
|
121922
121927
|
}
|
|
@@ -121943,22 +121948,22 @@ class nxDiv extends HTMLElement
|
|
|
121943
121948
|
}
|
|
121944
121949
|
|
|
121945
121950
|
#init = () => {
|
|
121946
|
-
|
|
121947
|
-
//console.log(this);
|
|
121948
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
121949
|
-
|
|
121950
|
-
/**
|
|
121951
|
-
* css style 적용
|
|
121952
|
-
*/
|
|
121951
|
+
// CSS Style 적용
|
|
121953
121952
|
for (const attr of this.attributes) {
|
|
121954
121953
|
if (attr.name.startsWith("css-")) {
|
|
121955
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
121956
121954
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
121957
121955
|
}
|
|
121958
121956
|
}
|
|
121959
121957
|
|
|
121958
|
+
// 2. HTML 내용 처리
|
|
121960
121959
|
this.originContents = this.innerHTML.trim();
|
|
121961
|
-
|
|
121960
|
+
|
|
121961
|
+
// Shadow DOM을 사용할 경우 내용을 안으로 옮김
|
|
121962
|
+
if (this.shadowRoot) {
|
|
121963
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
121964
|
+
this.innerHTML = ""; // 외부(Light DOM) 내용은 비움
|
|
121965
|
+
}
|
|
121966
|
+
// Shadow DOM을 안 쓰면 그대로 유지 (this.#root가 this이므로 별도 처리 불필요)
|
|
121962
121967
|
};
|
|
121963
121968
|
}
|
|
121964
121969
|
|
|
@@ -122244,28 +122249,37 @@ class nxPanel extends nxDiv {
|
|
|
122244
122249
|
|
|
122245
122250
|
customElements.define("nx-panel", nxPanel);
|
|
122246
122251
|
|
|
122247
|
-
class nxButtons extends
|
|
122248
|
-
|
|
122252
|
+
class nxButtons extends nxDiv {
|
|
122249
122253
|
constructor() {
|
|
122250
122254
|
super();
|
|
122251
122255
|
}
|
|
122252
122256
|
|
|
122253
122257
|
connectedCallback() {
|
|
122254
122258
|
if (super.connectedCallback()) this.#init();
|
|
122255
|
-
}
|
|
122259
|
+
}
|
|
122256
122260
|
|
|
122257
122261
|
#init = () => {
|
|
122258
|
-
|
|
122259
|
-
|
|
122260
|
-
|
|
122261
|
-
|
|
122262
|
-
|
|
122263
|
-
|
|
122264
|
-
|
|
122265
|
-
${this.originContents}
|
|
122262
|
+
// 1. 스타일과 내용을 합친 템플릿 생성
|
|
122263
|
+
const styleContent = `
|
|
122264
|
+
<style>
|
|
122265
|
+
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
122266
|
+
${ninegrid.getCustomPath(this, "nxButtons.css")}
|
|
122267
|
+
</style>
|
|
122266
122268
|
`;
|
|
122269
|
+
console.log("11111");
|
|
122270
|
+
const htmlTmpl = document.createElement("template");
|
|
122267
122271
|
|
|
122268
|
-
|
|
122272
|
+
// Shadow DOM일 때는 originContents를 옮겨야 하고,
|
|
122273
|
+
// Light DOM일 때는 이미 본문에 있으므로 스타일만 추가하면 됨
|
|
122274
|
+
if (this.shadowRoot) {
|
|
122275
|
+
htmlTmpl.innerHTML = `${styleContent}${this.originContents}`;
|
|
122276
|
+
this.root.appendChild(htmlTmpl.content.cloneNode(true));
|
|
122277
|
+
} else {
|
|
122278
|
+
// Light DOM 모드일 때: 스타일만 상단에 추가
|
|
122279
|
+
const styleDiv = document.createElement("div");
|
|
122280
|
+
styleDiv.innerHTML = styleContent;
|
|
122281
|
+
this.root.prepend(styleDiv);
|
|
122282
|
+
}
|
|
122269
122283
|
}
|
|
122270
122284
|
}
|
|
122271
122285
|
|
package/dist/bundle.esm.js
CHANGED
|
@@ -121834,33 +121834,48 @@ 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
|
+
// 1. 'use-shadow' 속성이 "false"가 아니면 기본적으로 Shadow DOM을 사용하도록 설정
|
|
121845
|
+
const useShadow = this.getAttribute("use-shadow") !== "false";
|
|
121846
|
+
|
|
121847
|
+
if (useShadow) {
|
|
121848
|
+
this.attachShadow({ mode: 'open' });
|
|
121849
|
+
this.#root = this.shadowRoot;
|
|
121850
|
+
} else {
|
|
121851
|
+
this.#root = this;
|
|
121852
|
+
}
|
|
121845
121853
|
}
|
|
121846
|
-
|
|
121854
|
+
|
|
121847
121855
|
connectedCallback() {
|
|
121848
121856
|
if (!this.#isInitialized) {
|
|
121849
121857
|
this.#init();
|
|
121850
|
-
this.#isInitialized = true;
|
|
121858
|
+
this.#isInitialized = true;
|
|
121851
121859
|
return true;
|
|
121852
121860
|
}
|
|
121853
|
-
|
|
121854
121861
|
return false;
|
|
121855
121862
|
}
|
|
121856
121863
|
|
|
121864
|
+
// 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
|
|
121865
|
+
#getElements() {
|
|
121866
|
+
return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
|
|
121867
|
+
}
|
|
121868
|
+
|
|
121869
|
+
// 자식 클래스에서 접근할 수 있도록 getter 제공
|
|
121870
|
+
get root() {
|
|
121871
|
+
return this.#root;
|
|
121872
|
+
}
|
|
121873
|
+
|
|
121857
121874
|
getData = () => {
|
|
121858
121875
|
const jsonData = {};
|
|
121859
|
-
|
|
121860
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
121861
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
121876
|
+
this.#getElements().forEach(el => {
|
|
121862
121877
|
const key = el.name;
|
|
121863
|
-
if (!key) return;
|
|
121878
|
+
if (!key) return;
|
|
121864
121879
|
|
|
121865
121880
|
let value;
|
|
121866
121881
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -121869,50 +121884,40 @@ class nxDiv extends HTMLElement
|
|
|
121869
121884
|
value = el.value;
|
|
121870
121885
|
}
|
|
121871
121886
|
|
|
121872
|
-
// 중복 name을 대비한 배열 처리
|
|
121873
121887
|
if (jsonData[key]) {
|
|
121874
|
-
if (!Array.isArray(jsonData[key]))
|
|
121875
|
-
jsonData[key] = [jsonData[key]];
|
|
121876
|
-
}
|
|
121888
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
121877
121889
|
jsonData[key].push(value);
|
|
121878
121890
|
} else {
|
|
121879
121891
|
jsonData[key] = value;
|
|
121880
121892
|
}
|
|
121881
121893
|
});
|
|
121882
|
-
|
|
121883
121894
|
return jsonData;
|
|
121884
121895
|
};
|
|
121885
121896
|
|
|
121886
121897
|
setData = (jsonData) => {
|
|
121887
|
-
|
|
121888
|
-
console.log("------", el);
|
|
121898
|
+
this.#getElements().forEach(el => {
|
|
121889
121899
|
el.removeEventListener("input", this.#changeHandler);
|
|
121890
121900
|
el.addEventListener("input", this.#changeHandler);
|
|
121891
121901
|
});
|
|
121892
121902
|
|
|
121893
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
121894
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
121895
|
-
return;
|
|
121896
|
-
}
|
|
121903
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
121897
121904
|
|
|
121898
121905
|
let bChanged = false;
|
|
121899
|
-
|
|
121906
|
+
this.#getElements().forEach(el => {
|
|
121900
121907
|
const key = el.name;
|
|
121901
121908
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
121902
121909
|
|
|
121903
121910
|
const value = jsonData[key];
|
|
121904
|
-
|
|
121905
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
121906
121911
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
121907
121912
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
121908
|
-
|
|
121909
|
-
el.checked
|
|
121913
|
+
const isChecked = (String(el.value) === String(value));
|
|
121914
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
121915
|
+
el.checked = isChecked;
|
|
121910
121916
|
} else {
|
|
121911
121917
|
if (el.value !== value) bChanged = true;
|
|
121912
121918
|
el.value = value;
|
|
121913
121919
|
}
|
|
121914
121920
|
} else {
|
|
121915
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
121916
121921
|
if (el.textContent !== value) bChanged = true;
|
|
121917
121922
|
el.textContent = value;
|
|
121918
121923
|
}
|
|
@@ -121939,22 +121944,22 @@ class nxDiv extends HTMLElement
|
|
|
121939
121944
|
}
|
|
121940
121945
|
|
|
121941
121946
|
#init = () => {
|
|
121942
|
-
|
|
121943
|
-
//console.log(this);
|
|
121944
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
121945
|
-
|
|
121946
|
-
/**
|
|
121947
|
-
* css style 적용
|
|
121948
|
-
*/
|
|
121947
|
+
// CSS Style 적용
|
|
121949
121948
|
for (const attr of this.attributes) {
|
|
121950
121949
|
if (attr.name.startsWith("css-")) {
|
|
121951
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
121952
121950
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
121953
121951
|
}
|
|
121954
121952
|
}
|
|
121955
121953
|
|
|
121954
|
+
// 2. HTML 내용 처리
|
|
121956
121955
|
this.originContents = this.innerHTML.trim();
|
|
121957
|
-
|
|
121956
|
+
|
|
121957
|
+
// Shadow DOM을 사용할 경우 내용을 안으로 옮김
|
|
121958
|
+
if (this.shadowRoot) {
|
|
121959
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
121960
|
+
this.innerHTML = ""; // 외부(Light DOM) 내용은 비움
|
|
121961
|
+
}
|
|
121962
|
+
// Shadow DOM을 안 쓰면 그대로 유지 (this.#root가 this이므로 별도 처리 불필요)
|
|
121958
121963
|
};
|
|
121959
121964
|
}
|
|
121960
121965
|
|
|
@@ -122240,28 +122245,37 @@ class nxPanel extends nxDiv {
|
|
|
122240
122245
|
|
|
122241
122246
|
customElements.define("nx-panel", nxPanel);
|
|
122242
122247
|
|
|
122243
|
-
class nxButtons extends
|
|
122244
|
-
|
|
122248
|
+
class nxButtons extends nxDiv {
|
|
122245
122249
|
constructor() {
|
|
122246
122250
|
super();
|
|
122247
122251
|
}
|
|
122248
122252
|
|
|
122249
122253
|
connectedCallback() {
|
|
122250
122254
|
if (super.connectedCallback()) this.#init();
|
|
122251
|
-
}
|
|
122255
|
+
}
|
|
122252
122256
|
|
|
122253
122257
|
#init = () => {
|
|
122254
|
-
|
|
122255
|
-
|
|
122256
|
-
|
|
122257
|
-
|
|
122258
|
-
|
|
122259
|
-
|
|
122260
|
-
|
|
122261
|
-
${this.originContents}
|
|
122258
|
+
// 1. 스타일과 내용을 합친 템플릿 생성
|
|
122259
|
+
const styleContent = `
|
|
122260
|
+
<style>
|
|
122261
|
+
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
122262
|
+
${ninegrid.getCustomPath(this, "nxButtons.css")}
|
|
122263
|
+
</style>
|
|
122262
122264
|
`;
|
|
122265
|
+
console.log("11111");
|
|
122266
|
+
const htmlTmpl = document.createElement("template");
|
|
122263
122267
|
|
|
122264
|
-
|
|
122268
|
+
// Shadow DOM일 때는 originContents를 옮겨야 하고,
|
|
122269
|
+
// Light DOM일 때는 이미 본문에 있으므로 스타일만 추가하면 됨
|
|
122270
|
+
if (this.shadowRoot) {
|
|
122271
|
+
htmlTmpl.innerHTML = `${styleContent}${this.originContents}`;
|
|
122272
|
+
this.root.appendChild(htmlTmpl.content.cloneNode(true));
|
|
122273
|
+
} else {
|
|
122274
|
+
// Light DOM 모드일 때: 스타일만 상단에 추가
|
|
122275
|
+
const styleDiv = document.createElement("div");
|
|
122276
|
+
styleDiv.innerHTML = styleContent;
|
|
122277
|
+
this.root.prepend(styleDiv);
|
|
122278
|
+
}
|
|
122265
122279
|
}
|
|
122266
122280
|
}
|
|
122267
122281
|
|
package/dist/nx/_nxDiv.js
CHANGED
|
@@ -1,32 +1,47 @@
|
|
|
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
|
+
// 1. 'use-shadow' 속성이 "false"가 아니면 기본적으로 Shadow DOM을 사용하도록 설정
|
|
11
|
+
const useShadow = this.getAttribute("use-shadow") !== "false";
|
|
12
|
+
|
|
13
|
+
if (useShadow) {
|
|
14
|
+
this.attachShadow({ mode: 'open' });
|
|
15
|
+
this.#root = this.shadowRoot;
|
|
16
|
+
} else {
|
|
17
|
+
this.#root = this;
|
|
18
|
+
}
|
|
11
19
|
}
|
|
12
|
-
|
|
20
|
+
|
|
13
21
|
connectedCallback() {
|
|
14
22
|
if (!this.#isInitialized) {
|
|
15
23
|
this.#init();
|
|
16
|
-
this.#isInitialized = true;
|
|
24
|
+
this.#isInitialized = true;
|
|
17
25
|
return true;
|
|
18
26
|
}
|
|
19
|
-
|
|
20
27
|
return false;
|
|
21
28
|
}
|
|
22
29
|
|
|
30
|
+
// 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
|
|
31
|
+
#getElements() {
|
|
32
|
+
return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 자식 클래스에서 접근할 수 있도록 getter 제공
|
|
36
|
+
get root() {
|
|
37
|
+
return this.#root;
|
|
38
|
+
}
|
|
39
|
+
|
|
23
40
|
getData = () => {
|
|
24
41
|
const jsonData = {};
|
|
25
|
-
|
|
26
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
27
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
42
|
+
this.#getElements().forEach(el => {
|
|
28
43
|
const key = el.name;
|
|
29
|
-
if (!key) return;
|
|
44
|
+
if (!key) return;
|
|
30
45
|
|
|
31
46
|
let value;
|
|
32
47
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -35,50 +50,40 @@ export class nxDiv extends HTMLElement
|
|
|
35
50
|
value = el.value;
|
|
36
51
|
}
|
|
37
52
|
|
|
38
|
-
// 중복 name을 대비한 배열 처리
|
|
39
53
|
if (jsonData[key]) {
|
|
40
|
-
if (!Array.isArray(jsonData[key]))
|
|
41
|
-
jsonData[key] = [jsonData[key]];
|
|
42
|
-
}
|
|
54
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
43
55
|
jsonData[key].push(value);
|
|
44
56
|
} else {
|
|
45
57
|
jsonData[key] = value;
|
|
46
58
|
}
|
|
47
59
|
});
|
|
48
|
-
|
|
49
60
|
return jsonData;
|
|
50
61
|
};
|
|
51
62
|
|
|
52
63
|
setData = (jsonData) => {
|
|
53
|
-
|
|
54
|
-
console.log("------", el);
|
|
64
|
+
this.#getElements().forEach(el => {
|
|
55
65
|
el.removeEventListener("input", this.#changeHandler);
|
|
56
66
|
el.addEventListener("input", this.#changeHandler);
|
|
57
67
|
});
|
|
58
68
|
|
|
59
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
60
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
69
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
63
70
|
|
|
64
71
|
let bChanged = false;
|
|
65
|
-
|
|
72
|
+
this.#getElements().forEach(el => {
|
|
66
73
|
const key = el.name;
|
|
67
74
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
68
75
|
|
|
69
76
|
const value = jsonData[key];
|
|
70
|
-
|
|
71
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
72
77
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
73
78
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
74
|
-
|
|
75
|
-
el.checked
|
|
79
|
+
const isChecked = (String(el.value) === String(value));
|
|
80
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
81
|
+
el.checked = isChecked;
|
|
76
82
|
} else {
|
|
77
83
|
if (el.value !== value) bChanged = true;
|
|
78
84
|
el.value = value;
|
|
79
85
|
}
|
|
80
86
|
} else {
|
|
81
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
82
87
|
if (el.textContent !== value) bChanged = true;
|
|
83
88
|
el.textContent = value;
|
|
84
89
|
}
|
|
@@ -105,21 +110,21 @@ export class nxDiv extends HTMLElement
|
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
#init = () => {
|
|
108
|
-
|
|
109
|
-
//console.log(this);
|
|
110
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* css style 적용
|
|
114
|
-
*/
|
|
113
|
+
// CSS Style 적용
|
|
115
114
|
for (const attr of this.attributes) {
|
|
116
115
|
if (attr.name.startsWith("css-")) {
|
|
117
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
118
116
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
119
117
|
}
|
|
120
118
|
}
|
|
121
119
|
|
|
120
|
+
// 2. HTML 내용 처리
|
|
122
121
|
this.originContents = this.innerHTML.trim();
|
|
123
|
-
|
|
122
|
+
|
|
123
|
+
// Shadow DOM을 사용할 경우 내용을 안으로 옮김
|
|
124
|
+
if (this.shadowRoot) {
|
|
125
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
126
|
+
this.innerHTML = ""; // 외부(Light DOM) 내용은 비움
|
|
127
|
+
}
|
|
128
|
+
// Shadow DOM을 안 쓰면 그대로 유지 (this.#root가 this이므로 별도 처리 불필요)
|
|
124
129
|
};
|
|
125
130
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import ninegrid from "../index.js";
|
|
2
|
+
|
|
3
|
+
export class nxDiv 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
|
+
console.log("------", el);
|
|
55
|
+
el.removeEventListener("input", this.#changeHandler);
|
|
56
|
+
el.addEventListener("input", this.#changeHandler);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (!jsonData || typeof jsonData !== 'object') {
|
|
60
|
+
console.error("setData: Invalid data provided. Expected an object.");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let bChanged = false;
|
|
65
|
+
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
66
|
+
const key = el.name;
|
|
67
|
+
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
68
|
+
|
|
69
|
+
const value = jsonData[key];
|
|
70
|
+
|
|
71
|
+
// 폼 요소에만 데이터를 설정합니다.
|
|
72
|
+
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
73
|
+
if (el.type === "checkbox" || el.type === "radio") {
|
|
74
|
+
if (el.checked !== (el.value === String(value))) bChanged = true;
|
|
75
|
+
el.checked = (el.value === String(value));
|
|
76
|
+
} else {
|
|
77
|
+
if (el.value !== value) bChanged = true;
|
|
78
|
+
el.value = value;
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
82
|
+
if (el.textContent !== value) bChanged = true;
|
|
83
|
+
el.textContent = value;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (bChanged) this.#changed(bChanged);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
initData = (jsonData) => {
|
|
91
|
+
this.setData(jsonData);
|
|
92
|
+
this.#changed(false);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
#changed = (v) => {
|
|
96
|
+
const parent = this.closest(".detail-wrapper");
|
|
97
|
+
if (parent) {
|
|
98
|
+
const el = parent.querySelector("nx-title2");
|
|
99
|
+
if (el) el.changed = v;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
#changeHandler = (e) => {
|
|
104
|
+
this.#changed(true);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#init = () => {
|
|
108
|
+
|
|
109
|
+
//console.log(this);
|
|
110
|
+
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* css style 적용
|
|
114
|
+
*/
|
|
115
|
+
for (const attr of this.attributes) {
|
|
116
|
+
if (attr.name.startsWith("css-")) {
|
|
117
|
+
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
118
|
+
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.originContents = this.innerHTML.trim();
|
|
123
|
+
this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
124
|
+
};
|
|
125
|
+
}
|
package/dist/nx/nxButtons.js
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
import ninegrid from "../index.js";
|
|
2
|
-
import {nxDiv} from "./_nxDiv.js";
|
|
3
|
-
|
|
4
|
-
class nxButtons extends HTMLElement {
|
|
2
|
+
import { nxDiv } from "./_nxDiv.js";
|
|
5
3
|
|
|
4
|
+
class nxButtons extends nxDiv {
|
|
6
5
|
constructor() {
|
|
7
6
|
super();
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
connectedCallback() {
|
|
11
10
|
if (super.connectedCallback()) this.#init();
|
|
12
|
-
}
|
|
11
|
+
}
|
|
13
12
|
|
|
14
13
|
#init = () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
${this.originContents}
|
|
14
|
+
// 1. 스타일과 내용을 합친 템플릿 생성
|
|
15
|
+
const styleContent = `
|
|
16
|
+
<style>
|
|
17
|
+
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
18
|
+
${ninegrid.getCustomPath(this, "nxButtons.css")}
|
|
19
|
+
</style>
|
|
23
20
|
`;
|
|
21
|
+
console.log("11111")
|
|
22
|
+
const htmlTmpl = document.createElement("template");
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
// Shadow DOM일 때는 originContents를 옮겨야 하고,
|
|
25
|
+
// Light DOM일 때는 이미 본문에 있으므로 스타일만 추가하면 됨
|
|
26
|
+
if (this.shadowRoot) {
|
|
27
|
+
htmlTmpl.innerHTML = `${styleContent}${this.originContents}`;
|
|
28
|
+
this.root.appendChild(htmlTmpl.content.cloneNode(true));
|
|
29
|
+
} else {
|
|
30
|
+
// Light DOM 모드일 때: 스타일만 상단에 추가
|
|
31
|
+
const styleDiv = document.createElement("div");
|
|
32
|
+
styleDiv.innerHTML = styleContent;
|
|
33
|
+
this.root.prepend(styleDiv);
|
|
34
|
+
}
|
|
26
35
|
}
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
customElements.define("nx-buttons", nxButtons);
|
|
38
|
+
customElements.define("nx-buttons", nxButtons);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import ninegrid from "../index.js";
|
|
2
|
+
import {nxDiv} from "./_nxDiv.js";
|
|
3
|
+
|
|
4
|
+
class nxButtons extends nxDiv {
|
|
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);
|
package/package.json
CHANGED
package/src/nx/_nxDiv.js
CHANGED
|
@@ -1,32 +1,47 @@
|
|
|
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
|
+
// 1. 'use-shadow' 속성이 "false"가 아니면 기본적으로 Shadow DOM을 사용하도록 설정
|
|
11
|
+
const useShadow = this.getAttribute("use-shadow") !== "false";
|
|
12
|
+
|
|
13
|
+
if (useShadow) {
|
|
14
|
+
this.attachShadow({ mode: 'open' });
|
|
15
|
+
this.#root = this.shadowRoot;
|
|
16
|
+
} else {
|
|
17
|
+
this.#root = this;
|
|
18
|
+
}
|
|
11
19
|
}
|
|
12
|
-
|
|
20
|
+
|
|
13
21
|
connectedCallback() {
|
|
14
22
|
if (!this.#isInitialized) {
|
|
15
23
|
this.#init();
|
|
16
|
-
this.#isInitialized = true;
|
|
24
|
+
this.#isInitialized = true;
|
|
17
25
|
return true;
|
|
18
26
|
}
|
|
19
|
-
|
|
20
27
|
return false;
|
|
21
28
|
}
|
|
22
29
|
|
|
30
|
+
// 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
|
|
31
|
+
#getElements() {
|
|
32
|
+
return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 자식 클래스에서 접근할 수 있도록 getter 제공
|
|
36
|
+
get root() {
|
|
37
|
+
return this.#root;
|
|
38
|
+
}
|
|
39
|
+
|
|
23
40
|
getData = () => {
|
|
24
41
|
const jsonData = {};
|
|
25
|
-
|
|
26
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
27
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
42
|
+
this.#getElements().forEach(el => {
|
|
28
43
|
const key = el.name;
|
|
29
|
-
if (!key) return;
|
|
44
|
+
if (!key) return;
|
|
30
45
|
|
|
31
46
|
let value;
|
|
32
47
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -35,50 +50,40 @@ export class nxDiv extends HTMLElement
|
|
|
35
50
|
value = el.value;
|
|
36
51
|
}
|
|
37
52
|
|
|
38
|
-
// 중복 name을 대비한 배열 처리
|
|
39
53
|
if (jsonData[key]) {
|
|
40
|
-
if (!Array.isArray(jsonData[key]))
|
|
41
|
-
jsonData[key] = [jsonData[key]];
|
|
42
|
-
}
|
|
54
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
43
55
|
jsonData[key].push(value);
|
|
44
56
|
} else {
|
|
45
57
|
jsonData[key] = value;
|
|
46
58
|
}
|
|
47
59
|
});
|
|
48
|
-
|
|
49
60
|
return jsonData;
|
|
50
61
|
};
|
|
51
62
|
|
|
52
63
|
setData = (jsonData) => {
|
|
53
|
-
|
|
54
|
-
console.log("------", el);
|
|
64
|
+
this.#getElements().forEach(el => {
|
|
55
65
|
el.removeEventListener("input", this.#changeHandler);
|
|
56
66
|
el.addEventListener("input", this.#changeHandler);
|
|
57
67
|
});
|
|
58
68
|
|
|
59
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
60
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
69
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
63
70
|
|
|
64
71
|
let bChanged = false;
|
|
65
|
-
|
|
72
|
+
this.#getElements().forEach(el => {
|
|
66
73
|
const key = el.name;
|
|
67
74
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
68
75
|
|
|
69
76
|
const value = jsonData[key];
|
|
70
|
-
|
|
71
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
72
77
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
73
78
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
74
|
-
|
|
75
|
-
el.checked
|
|
79
|
+
const isChecked = (String(el.value) === String(value));
|
|
80
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
81
|
+
el.checked = isChecked;
|
|
76
82
|
} else {
|
|
77
83
|
if (el.value !== value) bChanged = true;
|
|
78
84
|
el.value = value;
|
|
79
85
|
}
|
|
80
86
|
} else {
|
|
81
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
82
87
|
if (el.textContent !== value) bChanged = true;
|
|
83
88
|
el.textContent = value;
|
|
84
89
|
}
|
|
@@ -105,21 +110,21 @@ export class nxDiv extends HTMLElement
|
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
#init = () => {
|
|
108
|
-
|
|
109
|
-
//console.log(this);
|
|
110
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* css style 적용
|
|
114
|
-
*/
|
|
113
|
+
// CSS Style 적용
|
|
115
114
|
for (const attr of this.attributes) {
|
|
116
115
|
if (attr.name.startsWith("css-")) {
|
|
117
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
118
116
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
119
117
|
}
|
|
120
118
|
}
|
|
121
119
|
|
|
120
|
+
// 2. HTML 내용 처리
|
|
122
121
|
this.originContents = this.innerHTML.trim();
|
|
123
|
-
|
|
122
|
+
|
|
123
|
+
// Shadow DOM을 사용할 경우 내용을 안으로 옮김
|
|
124
|
+
if (this.shadowRoot) {
|
|
125
|
+
this.shadowRoot.innerHTML = this.originContents;
|
|
126
|
+
this.innerHTML = ""; // 외부(Light DOM) 내용은 비움
|
|
127
|
+
}
|
|
128
|
+
// Shadow DOM을 안 쓰면 그대로 유지 (this.#root가 this이므로 별도 처리 불필요)
|
|
124
129
|
};
|
|
125
130
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import ninegrid from "../index.js";
|
|
2
|
+
|
|
3
|
+
export class nxDiv 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
|
+
console.log("------", el);
|
|
55
|
+
el.removeEventListener("input", this.#changeHandler);
|
|
56
|
+
el.addEventListener("input", this.#changeHandler);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (!jsonData || typeof jsonData !== 'object') {
|
|
60
|
+
console.error("setData: Invalid data provided. Expected an object.");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let bChanged = false;
|
|
65
|
+
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
66
|
+
const key = el.name;
|
|
67
|
+
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
68
|
+
|
|
69
|
+
const value = jsonData[key];
|
|
70
|
+
|
|
71
|
+
// 폼 요소에만 데이터를 설정합니다.
|
|
72
|
+
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
73
|
+
if (el.type === "checkbox" || el.type === "radio") {
|
|
74
|
+
if (el.checked !== (el.value === String(value))) bChanged = true;
|
|
75
|
+
el.checked = (el.value === String(value));
|
|
76
|
+
} else {
|
|
77
|
+
if (el.value !== value) bChanged = true;
|
|
78
|
+
el.value = value;
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
82
|
+
if (el.textContent !== value) bChanged = true;
|
|
83
|
+
el.textContent = value;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (bChanged) this.#changed(bChanged);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
initData = (jsonData) => {
|
|
91
|
+
this.setData(jsonData);
|
|
92
|
+
this.#changed(false);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
#changed = (v) => {
|
|
96
|
+
const parent = this.closest(".detail-wrapper");
|
|
97
|
+
if (parent) {
|
|
98
|
+
const el = parent.querySelector("nx-title2");
|
|
99
|
+
if (el) el.changed = v;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
#changeHandler = (e) => {
|
|
104
|
+
this.#changed(true);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#init = () => {
|
|
108
|
+
|
|
109
|
+
//console.log(this);
|
|
110
|
+
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* css style 적용
|
|
114
|
+
*/
|
|
115
|
+
for (const attr of this.attributes) {
|
|
116
|
+
if (attr.name.startsWith("css-")) {
|
|
117
|
+
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
118
|
+
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.originContents = this.innerHTML.trim();
|
|
123
|
+
this.innerHTML = ""; // 기존 내부 HTML 제거
|
|
124
|
+
};
|
|
125
|
+
}
|
package/src/nx/nxButtons.js
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
import ninegrid from "../index.js";
|
|
2
|
-
import {nxDiv} from "./_nxDiv.js";
|
|
3
|
-
|
|
4
|
-
class nxButtons extends HTMLElement {
|
|
2
|
+
import { nxDiv } from "./_nxDiv.js";
|
|
5
3
|
|
|
4
|
+
class nxButtons extends nxDiv {
|
|
6
5
|
constructor() {
|
|
7
6
|
super();
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
connectedCallback() {
|
|
11
10
|
if (super.connectedCallback()) this.#init();
|
|
12
|
-
}
|
|
11
|
+
}
|
|
13
12
|
|
|
14
13
|
#init = () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
${this.originContents}
|
|
14
|
+
// 1. 스타일과 내용을 합친 템플릿 생성
|
|
15
|
+
const styleContent = `
|
|
16
|
+
<style>
|
|
17
|
+
@import "https://cdn.jsdelivr.net/npm/ninegrid@${ninegrid.version}/dist/css/nxButtons.css";
|
|
18
|
+
${ninegrid.getCustomPath(this, "nxButtons.css")}
|
|
19
|
+
</style>
|
|
23
20
|
`;
|
|
21
|
+
console.log("11111")
|
|
22
|
+
const htmlTmpl = document.createElement("template");
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
// Shadow DOM일 때는 originContents를 옮겨야 하고,
|
|
25
|
+
// Light DOM일 때는 이미 본문에 있으므로 스타일만 추가하면 됨
|
|
26
|
+
if (this.shadowRoot) {
|
|
27
|
+
htmlTmpl.innerHTML = `${styleContent}${this.originContents}`;
|
|
28
|
+
this.root.appendChild(htmlTmpl.content.cloneNode(true));
|
|
29
|
+
} else {
|
|
30
|
+
// Light DOM 모드일 때: 스타일만 상단에 추가
|
|
31
|
+
const styleDiv = document.createElement("div");
|
|
32
|
+
styleDiv.innerHTML = styleContent;
|
|
33
|
+
this.root.prepend(styleDiv);
|
|
34
|
+
}
|
|
26
35
|
}
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
customElements.define("nx-buttons", nxButtons);
|
|
38
|
+
customElements.define("nx-buttons", nxButtons);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import ninegrid from "../index.js";
|
|
2
|
+
import {nxDiv} from "./_nxDiv.js";
|
|
3
|
+
|
|
4
|
+
class nxButtons extends nxDiv {
|
|
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);
|