function nullish(value) {
return typeof value === "undefined" || value === null;
}
/**
* Element 생성을 위한 Object 형식
*/
class Blueprint {
data = null;
element = null;
children = [];
isTag = false;
content = "";
allowedInsertionPosition = {
pre: "afterbegin",
post: "beforeend"
};
/**
*
* @param {string|HTMLElement}tag
* @param {Object}option
* @param {Blueprint[]}children
*/
constructor(tag, option = {}, children = []) {
Object.freeze(this.allowedInsertionPosition);
this.data = {
tag: tag,
...option
};
if(typeof tag !== "string") {
this.isTag = true;
this.data.tag = tag.tagName;
this.element = tag;
this.content = tag.innerHTML;
}
this.produce();
}
/**
* Element 생성
* @returns {Blueprint} Self instance
*/
produce() {
if(!this.isTag) {
/**
* 생성
* @type {HTMLElement}
*/
this.element = document.createElement(this.data.tag);
}
while(this.element.attributes.length > 0) {
this.element.removeAttribute(this.element.attributes[0].name);
}
/**
* 속성 지정
*/
if(!nullish(this.data.attributes)) {
for(const name in this.data.attributes) {
const value = this.data.attributes[name];
this.element.setAttribute(name, value);
}
}
/**
* dataset 적용
*/
if(!nullish(this.data.dataset)) {
for(const name in this.data.dataset) {
this.element.dataset[name] = this.data.dataset[name];
}
}
if(!nullish(this.data.style)) {
for(const name in this.data.style) {
this.element.style[name] = this.data.style[name];
}
}
/**
* 리스너 지정
*/
const listener = this.data.listener;
if(!nullish(listener)) {
for(const eventType in listener) {
const callback = listener[eventType];
this.element.addEventListener(eventType, callback);
}
}
// 내용 초기화
this.element.innerHTML = this.content;
/**
* 자식 요소 생성
*/
const children = this.children;
if(children.length > 0) {
for(const child of children) {
this.element.appendChild(child.produce().getElement());
}
}
/**
* 텍스트 적용
*/
const text = this.data.text;
if(!nullish(text)) {
if(typeof text === "string") {
this.element.insertAdjacentText("beforeend", text);
}else {
for(const position in text) {
const positionValue = this.allowedInsertionPosition[position];
if(nullish(positionValue)) {
continue;
}
const content = "" + text[position];
this.element.insertAdjacentText(positionValue, content);
}
}
}
return this;
}
/**
* 내용 고정
*/
fixContent() {
this.content = this.element.innerHTML;
return this;
}
clearContent() {
[this.content, this.element.innerHTML] = ["", ""];
return this;
}
/**
* 생성 이후 옵션 지정
* @param optionType
* @param optionData
* @return {Blueprint} Self instance
*/
setOption(optionType, optionData) {
this.data[optionType] = optionData;
return this.produce();
}
/**
* 생성 이후 옵션 삭제
* @param optionType
* @param optionName
* @returns {Blueprint}
*/
removeOption(optionType, optionName) {
delete this.data[optionType][optionName];
return this.produce();
}
/**
* 자식 요소 추가
* @param children
* @return {Blueprint} Self instance
*/
addChildren(...children) {
for(const child of children) {
this.children.push(child);
}
return this.produce();
}
/**
* 자식 요소 제거, 인덱스 기반
* @param indexes
* @return {Blueprint} Self instance
*/
removeChildren(...indexes) {
for(const index of indexes) {
this.children.splice(index, 1);
}
return this.produce();
}
/**
*
* @return {null | HTMLElement}
*/
getElement() {
return this.element;
}
/**
*
* @return {null | Object}
*/
getInfo() {
return {...this.data};
}
/**
*
* @return {Blueprint[]}
*/
getChildrenInfo() {
return [...this.children];
}
}
HTMLElement.prototype.blueprint = function(...arguments) {
return new Blueprint(this, ...arguments);
};
NodeList.prototype.blueprint = function() {
return [...this].map(x => new Blueprint(x));
}
return typeof value === "undefined" || value === null;
}
/**
* Element 생성을 위한 Object 형식
*/
class Blueprint {
data = null;
element = null;
children = [];
isTag = false;
content = "";
allowedInsertionPosition = {
pre: "afterbegin",
post: "beforeend"
};
/**
*
* @param {string|HTMLElement}tag
* @param {Object}option
* @param {Blueprint[]}children
*/
constructor(tag, option = {}, children = []) {
Object.freeze(this.allowedInsertionPosition);
this.data = {
tag: tag,
...option
};
if(typeof tag !== "string") {
this.isTag = true;
this.data.tag = tag.tagName;
this.element = tag;
this.content = tag.innerHTML;
}
this.produce();
}
/**
* Element 생성
* @returns {Blueprint} Self instance
*/
produce() {
if(!this.isTag) {
/**
* 생성
* @type {HTMLElement}
*/
this.element = document.createElement(this.data.tag);
}
while(this.element.attributes.length > 0) {
this.element.removeAttribute(this.element.attributes[0].name);
}
/**
* 속성 지정
*/
if(!nullish(this.data.attributes)) {
for(const name in this.data.attributes) {
const value = this.data.attributes[name];
this.element.setAttribute(name, value);
}
}
/**
* dataset 적용
*/
if(!nullish(this.data.dataset)) {
for(const name in this.data.dataset) {
this.element.dataset[name] = this.data.dataset[name];
}
}
if(!nullish(this.data.style)) {
for(const name in this.data.style) {
this.element.style[name] = this.data.style[name];
}
}
/**
* 리스너 지정
*/
const listener = this.data.listener;
if(!nullish(listener)) {
for(const eventType in listener) {
const callback = listener[eventType];
this.element.addEventListener(eventType, callback);
}
}
// 내용 초기화
this.element.innerHTML = this.content;
/**
* 자식 요소 생성
*/
const children = this.children;
if(children.length > 0) {
for(const child of children) {
this.element.appendChild(child.produce().getElement());
}
}
/**
* 텍스트 적용
*/
const text = this.data.text;
if(!nullish(text)) {
if(typeof text === "string") {
this.element.insertAdjacentText("beforeend", text);
}else {
for(const position in text) {
const positionValue = this.allowedInsertionPosition[position];
if(nullish(positionValue)) {
continue;
}
const content = "" + text[position];
this.element.insertAdjacentText(positionValue, content);
}
}
}
return this;
}
/**
* 내용 고정
*/
fixContent() {
this.content = this.element.innerHTML;
return this;
}
clearContent() {
[this.content, this.element.innerHTML] = ["", ""];
return this;
}
/**
* 생성 이후 옵션 지정
* @param optionType
* @param optionData
* @return {Blueprint} Self instance
*/
setOption(optionType, optionData) {
this.data[optionType] = optionData;
return this.produce();
}
/**
* 생성 이후 옵션 삭제
* @param optionType
* @param optionName
* @returns {Blueprint}
*/
removeOption(optionType, optionName) {
delete this.data[optionType][optionName];
return this.produce();
}
/**
* 자식 요소 추가
* @param children
* @return {Blueprint} Self instance
*/
addChildren(...children) {
for(const child of children) {
this.children.push(child);
}
return this.produce();
}
/**
* 자식 요소 제거, 인덱스 기반
* @param indexes
* @return {Blueprint} Self instance
*/
removeChildren(...indexes) {
for(const index of indexes) {
this.children.splice(index, 1);
}
return this.produce();
}
/**
*
* @return {null | HTMLElement}
*/
getElement() {
return this.element;
}
/**
*
* @return {null | Object}
*/
getInfo() {
return {...this.data};
}
/**
*
* @return {Blueprint[]}
*/
getChildrenInfo() {
return [...this.children];
}
}
HTMLElement.prototype.blueprint = function(...arguments) {
return new Blueprint(this, ...arguments);
};
NodeList.prototype.blueprint = function() {
return [...this].map(x => new Blueprint(x));
}
점점 제이쿼리처럼됨...
흐음..허어..
댓글 0