ninegrid2 6.1248.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 +62 -50
- package/dist/bundle.esm.js +62 -50
- package/dist/etc/ninegridContainer.js +0 -2
- package/dist/nx/_nxDiv.js +42 -37
- package/dist/nx/_nxDiv.js.bak2 +125 -0
- package/dist/nx/nxButtons.js +22 -13
- package/dist/nx/nxButtons.js.bak +29 -0
- package/package.json +1 -1
- package/src/etc/ninegridContainer.js +0 -2
- package/src/nx/_nxDiv.js +42 -37
- package/src/nx/_nxDiv.js.bak2 +125 -0
- package/src/nx/nxButtons.js +22 -13
- package/src/nx/nxButtons.js.bak +29 -0
package/dist/bundle.cjs.js
CHANGED
|
@@ -118768,8 +118768,6 @@ class NineGridContainer extends HTMLElement
|
|
|
118768
118768
|
this.querySelectorAll("nx-buttons *").forEach(v => {v.grid = this;});
|
|
118769
118769
|
$(this.shadowRoot.querySelector("ng-head").shadowRoot.querySelector("ng-custom")).append(this.querySelectorAll("nx-buttons"));
|
|
118770
118770
|
|
|
118771
|
-
|
|
118772
|
-
|
|
118773
118771
|
this.#prepare();
|
|
118774
118772
|
|
|
118775
118773
|
this.createTemplate();
|
|
@@ -121840,33 +121838,48 @@ class nxTitle extends HTMLElement {
|
|
|
121840
121838
|
|
|
121841
121839
|
customElements.define("nx-title", nxTitle);
|
|
121842
121840
|
|
|
121843
|
-
class nxDiv extends HTMLElement
|
|
121844
|
-
{
|
|
121841
|
+
class nxDiv extends HTMLElement {
|
|
121845
121842
|
originContents;
|
|
121846
121843
|
#isInitialized = false;
|
|
121844
|
+
#root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
|
|
121847
121845
|
|
|
121848
|
-
constructor
|
|
121846
|
+
constructor() {
|
|
121849
121847
|
super();
|
|
121850
|
-
|
|
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
|
+
}
|
|
121851
121857
|
}
|
|
121852
|
-
|
|
121858
|
+
|
|
121853
121859
|
connectedCallback() {
|
|
121854
121860
|
if (!this.#isInitialized) {
|
|
121855
121861
|
this.#init();
|
|
121856
|
-
this.#isInitialized = true;
|
|
121862
|
+
this.#isInitialized = true;
|
|
121857
121863
|
return true;
|
|
121858
121864
|
}
|
|
121859
|
-
|
|
121860
121865
|
return false;
|
|
121861
121866
|
}
|
|
121862
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
|
+
|
|
121863
121878
|
getData = () => {
|
|
121864
121879
|
const jsonData = {};
|
|
121865
|
-
|
|
121866
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
121867
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
121880
|
+
this.#getElements().forEach(el => {
|
|
121868
121881
|
const key = el.name;
|
|
121869
|
-
if (!key) return;
|
|
121882
|
+
if (!key) return;
|
|
121870
121883
|
|
|
121871
121884
|
let value;
|
|
121872
121885
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -121875,50 +121888,40 @@ class nxDiv extends HTMLElement
|
|
|
121875
121888
|
value = el.value;
|
|
121876
121889
|
}
|
|
121877
121890
|
|
|
121878
|
-
// 중복 name을 대비한 배열 처리
|
|
121879
121891
|
if (jsonData[key]) {
|
|
121880
|
-
if (!Array.isArray(jsonData[key]))
|
|
121881
|
-
jsonData[key] = [jsonData[key]];
|
|
121882
|
-
}
|
|
121892
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
121883
121893
|
jsonData[key].push(value);
|
|
121884
121894
|
} else {
|
|
121885
121895
|
jsonData[key] = value;
|
|
121886
121896
|
}
|
|
121887
121897
|
});
|
|
121888
|
-
|
|
121889
121898
|
return jsonData;
|
|
121890
121899
|
};
|
|
121891
121900
|
|
|
121892
121901
|
setData = (jsonData) => {
|
|
121893
|
-
|
|
121894
|
-
console.log("------", el);
|
|
121902
|
+
this.#getElements().forEach(el => {
|
|
121895
121903
|
el.removeEventListener("input", this.#changeHandler);
|
|
121896
121904
|
el.addEventListener("input", this.#changeHandler);
|
|
121897
121905
|
});
|
|
121898
121906
|
|
|
121899
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
121900
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
121901
|
-
return;
|
|
121902
|
-
}
|
|
121907
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
121903
121908
|
|
|
121904
121909
|
let bChanged = false;
|
|
121905
|
-
|
|
121910
|
+
this.#getElements().forEach(el => {
|
|
121906
121911
|
const key = el.name;
|
|
121907
121912
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
121908
121913
|
|
|
121909
121914
|
const value = jsonData[key];
|
|
121910
|
-
|
|
121911
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
121912
121915
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
121913
121916
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
121914
|
-
|
|
121915
|
-
el.checked
|
|
121917
|
+
const isChecked = (String(el.value) === String(value));
|
|
121918
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
121919
|
+
el.checked = isChecked;
|
|
121916
121920
|
} else {
|
|
121917
121921
|
if (el.value !== value) bChanged = true;
|
|
121918
121922
|
el.value = value;
|
|
121919
121923
|
}
|
|
121920
121924
|
} else {
|
|
121921
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
121922
121925
|
if (el.textContent !== value) bChanged = true;
|
|
121923
121926
|
el.textContent = value;
|
|
121924
121927
|
}
|
|
@@ -121945,22 +121948,22 @@ class nxDiv extends HTMLElement
|
|
|
121945
121948
|
}
|
|
121946
121949
|
|
|
121947
121950
|
#init = () => {
|
|
121948
|
-
|
|
121949
|
-
//console.log(this);
|
|
121950
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
121951
|
-
|
|
121952
|
-
/**
|
|
121953
|
-
* css style 적용
|
|
121954
|
-
*/
|
|
121951
|
+
// CSS Style 적용
|
|
121955
121952
|
for (const attr of this.attributes) {
|
|
121956
121953
|
if (attr.name.startsWith("css-")) {
|
|
121957
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
121958
121954
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
121959
121955
|
}
|
|
121960
121956
|
}
|
|
121961
121957
|
|
|
121958
|
+
// 2. HTML 내용 처리
|
|
121962
121959
|
this.originContents = this.innerHTML.trim();
|
|
121963
|
-
|
|
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이므로 별도 처리 불필요)
|
|
121964
121967
|
};
|
|
121965
121968
|
}
|
|
121966
121969
|
|
|
@@ -122247,27 +122250,36 @@ class nxPanel extends nxDiv {
|
|
|
122247
122250
|
customElements.define("nx-panel", nxPanel);
|
|
122248
122251
|
|
|
122249
122252
|
class nxButtons extends nxDiv {
|
|
122250
|
-
|
|
122251
122253
|
constructor() {
|
|
122252
122254
|
super();
|
|
122253
122255
|
}
|
|
122254
122256
|
|
|
122255
122257
|
connectedCallback() {
|
|
122256
122258
|
if (super.connectedCallback()) this.#init();
|
|
122257
|
-
}
|
|
122259
|
+
}
|
|
122258
122260
|
|
|
122259
122261
|
#init = () => {
|
|
122260
|
-
|
|
122261
|
-
|
|
122262
|
-
|
|
122263
|
-
|
|
122264
|
-
|
|
122265
|
-
|
|
122266
|
-
|
|
122267
|
-
${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>
|
|
122268
122268
|
`;
|
|
122269
|
+
console.log("11111");
|
|
122270
|
+
const htmlTmpl = document.createElement("template");
|
|
122269
122271
|
|
|
122270
|
-
|
|
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
|
+
}
|
|
122271
122283
|
}
|
|
122272
122284
|
}
|
|
122273
122285
|
|
package/dist/bundle.esm.js
CHANGED
|
@@ -118764,8 +118764,6 @@ class NineGridContainer extends HTMLElement
|
|
|
118764
118764
|
this.querySelectorAll("nx-buttons *").forEach(v => {v.grid = this;});
|
|
118765
118765
|
$(this.shadowRoot.querySelector("ng-head").shadowRoot.querySelector("ng-custom")).append(this.querySelectorAll("nx-buttons"));
|
|
118766
118766
|
|
|
118767
|
-
|
|
118768
|
-
|
|
118769
118767
|
this.#prepare();
|
|
118770
118768
|
|
|
118771
118769
|
this.createTemplate();
|
|
@@ -121836,33 +121834,48 @@ class nxTitle extends HTMLElement {
|
|
|
121836
121834
|
|
|
121837
121835
|
customElements.define("nx-title", nxTitle);
|
|
121838
121836
|
|
|
121839
|
-
class nxDiv extends HTMLElement
|
|
121840
|
-
{
|
|
121837
|
+
class nxDiv extends HTMLElement {
|
|
121841
121838
|
originContents;
|
|
121842
121839
|
#isInitialized = false;
|
|
121840
|
+
#root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
|
|
121843
121841
|
|
|
121844
|
-
constructor
|
|
121842
|
+
constructor() {
|
|
121845
121843
|
super();
|
|
121846
|
-
|
|
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
|
+
}
|
|
121847
121853
|
}
|
|
121848
|
-
|
|
121854
|
+
|
|
121849
121855
|
connectedCallback() {
|
|
121850
121856
|
if (!this.#isInitialized) {
|
|
121851
121857
|
this.#init();
|
|
121852
|
-
this.#isInitialized = true;
|
|
121858
|
+
this.#isInitialized = true;
|
|
121853
121859
|
return true;
|
|
121854
121860
|
}
|
|
121855
|
-
|
|
121856
121861
|
return false;
|
|
121857
121862
|
}
|
|
121858
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
|
+
|
|
121859
121874
|
getData = () => {
|
|
121860
121875
|
const jsonData = {};
|
|
121861
|
-
|
|
121862
|
-
// Shadow DOM 내의 폼 요소만 선택
|
|
121863
|
-
ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
|
|
121876
|
+
this.#getElements().forEach(el => {
|
|
121864
121877
|
const key = el.name;
|
|
121865
|
-
if (!key) return;
|
|
121878
|
+
if (!key) return;
|
|
121866
121879
|
|
|
121867
121880
|
let value;
|
|
121868
121881
|
if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
|
|
@@ -121871,50 +121884,40 @@ class nxDiv extends HTMLElement
|
|
|
121871
121884
|
value = el.value;
|
|
121872
121885
|
}
|
|
121873
121886
|
|
|
121874
|
-
// 중복 name을 대비한 배열 처리
|
|
121875
121887
|
if (jsonData[key]) {
|
|
121876
|
-
if (!Array.isArray(jsonData[key]))
|
|
121877
|
-
jsonData[key] = [jsonData[key]];
|
|
121878
|
-
}
|
|
121888
|
+
if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
|
|
121879
121889
|
jsonData[key].push(value);
|
|
121880
121890
|
} else {
|
|
121881
121891
|
jsonData[key] = value;
|
|
121882
121892
|
}
|
|
121883
121893
|
});
|
|
121884
|
-
|
|
121885
121894
|
return jsonData;
|
|
121886
121895
|
};
|
|
121887
121896
|
|
|
121888
121897
|
setData = (jsonData) => {
|
|
121889
|
-
|
|
121890
|
-
console.log("------", el);
|
|
121898
|
+
this.#getElements().forEach(el => {
|
|
121891
121899
|
el.removeEventListener("input", this.#changeHandler);
|
|
121892
121900
|
el.addEventListener("input", this.#changeHandler);
|
|
121893
121901
|
});
|
|
121894
121902
|
|
|
121895
|
-
if (!jsonData || typeof jsonData !== 'object')
|
|
121896
|
-
console.error("setData: Invalid data provided. Expected an object.");
|
|
121897
|
-
return;
|
|
121898
|
-
}
|
|
121903
|
+
if (!jsonData || typeof jsonData !== 'object') return;
|
|
121899
121904
|
|
|
121900
121905
|
let bChanged = false;
|
|
121901
|
-
|
|
121906
|
+
this.#getElements().forEach(el => {
|
|
121902
121907
|
const key = el.name;
|
|
121903
121908
|
if (!key || !jsonData.hasOwnProperty(key)) return;
|
|
121904
121909
|
|
|
121905
121910
|
const value = jsonData[key];
|
|
121906
|
-
|
|
121907
|
-
// 폼 요소에만 데이터를 설정합니다.
|
|
121908
121911
|
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
121909
121912
|
if (el.type === "checkbox" || el.type === "radio") {
|
|
121910
|
-
|
|
121911
|
-
el.checked
|
|
121913
|
+
const isChecked = (String(el.value) === String(value));
|
|
121914
|
+
if (el.checked !== isChecked) bChanged = true;
|
|
121915
|
+
el.checked = isChecked;
|
|
121912
121916
|
} else {
|
|
121913
121917
|
if (el.value !== value) bChanged = true;
|
|
121914
121918
|
el.value = value;
|
|
121915
121919
|
}
|
|
121916
121920
|
} else {
|
|
121917
|
-
// 폼 요소가 아닌 경우, textContent를 사용합니다.
|
|
121918
121921
|
if (el.textContent !== value) bChanged = true;
|
|
121919
121922
|
el.textContent = value;
|
|
121920
121923
|
}
|
|
@@ -121941,22 +121944,22 @@ class nxDiv extends HTMLElement
|
|
|
121941
121944
|
}
|
|
121942
121945
|
|
|
121943
121946
|
#init = () => {
|
|
121944
|
-
|
|
121945
|
-
//console.log(this);
|
|
121946
|
-
//console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
|
|
121947
|
-
|
|
121948
|
-
/**
|
|
121949
|
-
* css style 적용
|
|
121950
|
-
*/
|
|
121947
|
+
// CSS Style 적용
|
|
121951
121948
|
for (const attr of this.attributes) {
|
|
121952
121949
|
if (attr.name.startsWith("css-")) {
|
|
121953
|
-
// "css-" 접두사를 제거하고 CSS 속성명으로 변환
|
|
121954
121950
|
this.style.setProperty(attr.name.substring(4), attr.value);
|
|
121955
121951
|
}
|
|
121956
121952
|
}
|
|
121957
121953
|
|
|
121954
|
+
// 2. HTML 내용 처리
|
|
121958
121955
|
this.originContents = this.innerHTML.trim();
|
|
121959
|
-
|
|
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이므로 별도 처리 불필요)
|
|
121960
121963
|
};
|
|
121961
121964
|
}
|
|
121962
121965
|
|
|
@@ -122243,27 +122246,36 @@ class nxPanel extends nxDiv {
|
|
|
122243
122246
|
customElements.define("nx-panel", nxPanel);
|
|
122244
122247
|
|
|
122245
122248
|
class nxButtons extends nxDiv {
|
|
122246
|
-
|
|
122247
122249
|
constructor() {
|
|
122248
122250
|
super();
|
|
122249
122251
|
}
|
|
122250
122252
|
|
|
122251
122253
|
connectedCallback() {
|
|
122252
122254
|
if (super.connectedCallback()) this.#init();
|
|
122253
|
-
}
|
|
122255
|
+
}
|
|
122254
122256
|
|
|
122255
122257
|
#init = () => {
|
|
122256
|
-
|
|
122257
|
-
|
|
122258
|
-
|
|
122259
|
-
|
|
122260
|
-
|
|
122261
|
-
|
|
122262
|
-
|
|
122263
|
-
${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>
|
|
122264
122264
|
`;
|
|
122265
|
+
console.log("11111");
|
|
122266
|
+
const htmlTmpl = document.createElement("template");
|
|
122265
122267
|
|
|
122266
|
-
|
|
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
|
+
}
|
|
122267
122279
|
}
|
|
122268
122280
|
}
|
|
122269
122281
|
|
|
@@ -653,8 +653,6 @@ export class NineGridContainer extends HTMLElement
|
|
|
653
653
|
this.querySelectorAll("nx-buttons *").forEach(v => {v.grid = this;});
|
|
654
654
|
$(this.shadowRoot.querySelector("ng-head").shadowRoot.querySelector("ng-custom")).append(this.querySelectorAll("nx-buttons"));
|
|
655
655
|
|
|
656
|
-
|
|
657
|
-
|
|
658
656
|
this.#prepare();
|
|
659
657
|
|
|
660
658
|
this.createTemplate();
|
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";
|
|
2
|
+
import { nxDiv } from "./_nxDiv.js";
|
|
3
3
|
|
|
4
4
|
class nxButtons extends nxDiv {
|
|
5
|
-
|
|
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
|
@@ -653,8 +653,6 @@ export class NineGridContainer extends HTMLElement
|
|
|
653
653
|
this.querySelectorAll("nx-buttons *").forEach(v => {v.grid = this;});
|
|
654
654
|
$(this.shadowRoot.querySelector("ng-head").shadowRoot.querySelector("ng-custom")).append(this.querySelectorAll("nx-buttons"));
|
|
655
655
|
|
|
656
|
-
|
|
657
|
-
|
|
658
656
|
this.#prepare();
|
|
659
657
|
|
|
660
658
|
this.createTemplate();
|
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";
|
|
2
|
+
import { nxDiv } from "./_nxDiv.js";
|
|
3
3
|
|
|
4
4
|
class nxButtons extends nxDiv {
|
|
5
|
-
|
|
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);
|