diff --git a/client/index.html b/client/index.html index 565bbe4..ad60dbb 100644 --- a/client/index.html +++ b/client/index.html @@ -5,13 +5,27 @@ - - Document + + + calculator -

- hello - world -

+
+
+ + +
+ +
+
+ +
+ + +
+ + + +
-
+
diff --git a/client/lib/dom/attr.js b/client/lib/dom/attr.js new file mode 100644 index 0000000..b71e0d6 --- /dev/null +++ b/client/lib/dom/attr.js @@ -0,0 +1,113 @@ +/* + +// IIFE 패턴 + +const attr = (function(){ + function getAttr(node,prop){ + // node = '.first' + // prop = 'class' + + if(typeof node === 'string'){ + node = getNode(node); + } + + return node.getAttribute(prop); + + } + + + + // computed property + function setAttr(node,prop,value){ + // validation : 확인 + if(typeof node === 'string') node = getNode(node); + if(typeof prop !== 'string') throw new TypeError('setAttr 함수의 두 번째 인자는 문자 타입 이어야 합니다.') + + if(prop.includes('data')){ + let rest = prop.slice(5); + node.dataset[rest] = value; + } + + if(!value) throw new SyntaxError('setAttr 함수의 세 번째 인자는 필수값입니다.') + + node.setAttribute(prop,value); + + } + + + + + // const attr = (node,prop,value) => !value ? getAttr(node,prop) : setAttr(node,prop,value); + + function attr(node,prop,value){ + + // if(!value){ + // return getAttr(node,prop); + // }else{ + // setAttr(node,prop,value); + // } + + return !value ? getAttr(node,prop) : setAttr(node,prop,value); + + + } + + // incapsulation // 캡슐화 + // 정보 은닉 + + + return attr + +})() + + +// incapsulation // 캡슐화 +// 정보 은닉 + + +attr() + + */ + +function getAttr(node, prop) { + // node = '.first' + // prop = 'class' + + if (typeof node === 'string') { + node = getNode(node); + } + + return node.getAttribute(prop); +} + +// computed property +function setAttr(node, prop, value) { + // validation : 확인 + if (typeof node === 'string') node = getNode(node); + if (typeof prop !== 'string') + throw new TypeError( + 'setAttr 함수의 두 번째 인자는 문자 타입 이어야 합니다.' + ); + + if (prop.includes('data')) { + let rest = prop.slice(5); + node.dataset[rest] = value; + } + + if (!value) + throw new SyntaxError('setAttr 함수의 세 번째 인자는 필수값입니다.'); + + node.setAttribute(prop, value); +} + +// const attr = (node,prop,value) => !value ? getAttr(node,prop) : setAttr(node,prop,value); + +function attr(node, prop, value) { + // if(!value){ + // return getAttr(node,prop); + // }else{ + // setAttr(node,prop,value); + // } + + return !value ? getAttr(node, prop) : setAttr(node, prop, value); +} diff --git a/client/lib/dom/bindEvent.js b/client/lib/dom/bindEvent.js new file mode 100644 index 0000000..1397765 --- /dev/null +++ b/client/lib/dom/bindEvent.js @@ -0,0 +1,16 @@ + +function bindEvent(node,type,handler){ + if(typeof node === 'string'){ + node = getNode(node); + } + + if(!(/mouseenter|click|mousemove|mouseleave/g.test(type))){ + typeError('bindEvent 함수의 두 번째 인자는 유효한 이벤트 타입 이어야 합니다.') + } + + + node.addEventListener(type,handler); + + return ()=> node.removeEventListener(type,handler); + +} diff --git a/client/lib/dom/css.js b/client/lib/dom/css.js new file mode 100644 index 0000000..0d220bb --- /dev/null +++ b/client/lib/dom/css.js @@ -0,0 +1,84 @@ + +export function addClass(node,className){ + + if(typeof node === 'string') node = getNode(node); + + if(typeof className !== 'string'){ + typeError('addClass 함수의 두 번째 인자는 문자 타입 이어야 합니다.'); + } + + node.classList.add(className) + +} + +// 변경하기 : 대상의 클래스를 지운다. +export function removeClass(node,className){ + if(typeof node === 'string') node = getNode(node); + + if(!className){ + node.className = '' + return; + } + + if(typeof className !== 'string'){ + typeError('removeClass 함수의 두 번째 인자는 문자 타입 이어야 합니다.'); + } + + node.classList.remove(className) +} + + +export function toggleClass(node,className){ + if(typeof node === 'string') node = getNode(node); + if(typeof className !== 'string'){ + typeError('toggleClass 함수의 두 번째 인자는 문자 타입 이어야 합니다.'); + } + + node.classList.toggle(className) +} + + + + + + +function getCss(node,prop){ + if(typeof node === 'string'){ + node = getNode(node); + } + + if(!(prop in document.body.style)){ + syntaxError('getCSS 함수의 두 번째 인자인 prop은 유효한 css 속성이 아닙니다.') + } + return getComputedStyle(node)[prop] +} + + +// jQuery + +// 대상에게 원하는 css 속성을 추가 = set +function setCss(node,prop,value){ + if(typeof node === 'string'){ + node = getNode(node); + } + if(!(prop in document.body.style)){ + syntaxError('setCSS 함수의 두 번째 인자인 prop은 유효한 css 속성이 아닙니다.') + } + if(!value){ + syntaxError('setCSS 함수의 세 번째 인자는 필수값 입니다.') + } + + // if(value.replace(/\s+/g,'') === ''){ + + // } + + node.style[prop] = value; + +} + + +export const css = (node,prop,value) => { + return !value ? getCss(node,prop) : setCss(node,prop,value) +} + + \ No newline at end of file diff --git a/client/lib/dom/getNode.js b/client/lib/dom/getNode.js new file mode 100644 index 0000000..39b3fc9 --- /dev/null +++ b/client/lib/dom/getNode.js @@ -0,0 +1,20 @@ + +export function getNode(node){ + if(typeof node !== 'string'){ + throw new Error('getNode 함수의 인자는 문자 타입 이여야 합니다.'); + } + + // if(!isString(node)) typeError('에러가 발생했습니다.'); + + return document.querySelector(node) +} + + +export function getNodes(node){ + if(typeof node !== 'string'){ + throw new Error('getNode 함수의 인자는 문자 타입 이여야 합니다.'); + } + + return document.querySelectorAll(node) +} + diff --git a/client/lib/dom/index.js b/client/lib/dom/index.js new file mode 100644 index 0000000..1eb454d --- /dev/null +++ b/client/lib/dom/index.js @@ -0,0 +1,6 @@ + + + +export * from './css.js'; +export * from './getNode.js'; +export * from './insert.js'; \ No newline at end of file diff --git a/client/lib/dom/insert.js b/client/lib/dom/insert.js new file mode 100644 index 0000000..134d48b --- /dev/null +++ b/client/lib/dom/insert.js @@ -0,0 +1,33 @@ +export function insertBefore(node, text) { + if (typeof node === 'string') node = getNode(node); + + if (node.nodeType !== document.ELEMENT_NODE) { + typeError('insertBefore 함수의 첫 번째 인자는 ELEMENT 노드여야 합니다.'); + } + + node.insertAdjacentHTML('beforebegin', text); +} + +export function insertFirst(node, text) { + if (typeof node === 'string') node = getNode(node); + if (node.nodeType !== document.ELEMENT_NODE) typeError('insertFirst 함수의 첫 번째 인자는 ELEMENT 노드여야 합니다.'); + node.insertAdjacentHTML('afterbegin', text); +} + + + +export function insertLast(node, text) { + if (typeof node === 'string') node = getNode(node); + if (node.nodeType !== document.ELEMENT_NODE) { + refError('insertLast 함수의 첫 번째 인자는 ELEMENT 노드여야 합니다.'); + } + node.insertAdjacentHTML('beforeend', text); +} + +export function insertAfter(node, text) { + if (typeof node === 'string') node = getNode(node); + if (node.nodeType !== document.ELEMENT_NODE) { + refError('insertAfter 함수의 첫 번째 인자는 ELEMENT 노드여야 합니다.'); + } + node.insertAdjacentHTML('afterend', text); +} diff --git a/client/lib/error/typeError.js b/client/lib/error/typeError.js new file mode 100644 index 0000000..0b0335f --- /dev/null +++ b/client/lib/error/typeError.js @@ -0,0 +1,22 @@ + +// 📂 typeError.js +function typeError(message){ + throw new TypeError( message ); +} + +// 📂 refError.js +function refError(message){ + throw new ReferenceError( message ); +} + +// 📂 syntaxError.js +function syntaxError(message){ + throw new SyntaxError( message ); +} + + + + + + + diff --git a/client/lib/index.js b/client/lib/index.js new file mode 100644 index 0000000..d9ed07b --- /dev/null +++ b/client/lib/index.js @@ -0,0 +1,2 @@ +export * from "./dom/index.js"; +// export * from "./dom/su.js"; \ No newline at end of file diff --git a/client/main.js b/client/main.js index 3fff1d8..338cb35 100644 --- a/client/main.js +++ b/client/main.js @@ -1,2 +1,92 @@ +import {getNode, css, addClass, removeClass} from "./lib/index.js"; -console.log("hello") + + + + + + + + + + + +//const calculator = document.querySelector('.calculator'); +const result = document.querySelector('.result'); +const firstNumber = document.querySelector('#firstNumber'); +const secondNumber = document.querySelector('#secondNumber'); +const done = document.querySelector('#done'); + +//const operator = document.querySelector('.operator'); + +// function getInputValue() { + +// if( typeof node === 'string') { +// node = getNode(node); + +// if(node.tagName !== 'INPUT') { +// throw new Error("에러입니다."); +// } + +// return node.value; +// } +// } + + + +function handler(e) { +e.preventDefault(); + + //let target = e.target; + + //console.log(target); + + + // console.log( firstNumber.value); + + let firstValue = firstNumber.value; + + //console.log(firstValue); + + let secondValue = secondNumber.value; + + //console.log( secondNumber.value); + // secondNumber.value; + + //console.log(done); + + let total = Number(firstValue) + Number(secondValue); + console.log(total); + + result.textContent = ''; + result.insertAdjacentHTML('afterbegin', total); + + +} + + +function inputHandler() { + + let firstValue = firstNumber.value; + + //console.log(firstValue); + + let secondValue = secondNumber.value; + + //console.log( secondNumber.value); + // secondNumber.value; + + //console.log(done); + + let total = Number(firstValue) + Number(secondValue); + console.log(total); + + result.textContent = ''; + result.insertAdjacentHTML('afterbegin', total); + +} + +done.addEventListener('click', handler); + + +firstNumber.addEventListener('change', inputHandler); \ No newline at end of file diff --git a/client/style.css b/client/style.css index 0f4eafd..9ab16b0 100644 --- a/client/style.css +++ b/client/style.css @@ -1,11 +1,88 @@ -h1 { - height: 100vh; - display: flex; - align-items: center; - justify-content: center; - /* margin: 0; +body{ + background: #f6f6f6; +} + +.calculator{ position: absolute; left: 50%; top: 50%; - transform: translate(-50%, -50%); */ + transform: translate(-50%,-50%); + display: flex; + justify-content: center; + align-items: center; +} + +.calculator > div{ + position: relative; +} + +input[type=number]{ + max-width: 10rem; + font-size: 2rem; + padding: .5rem; + background: transparent; + border-radius: 0.3rem; + border: 1px solid gray; + color:rgb(83, 83, 83); + text-align: center; +} + +.operator{ + font-size: 1.5rem; + margin: 0 1rem; +} + + + +input[type=submit]{ + padding: 1rem; + font-size: 1rem; + margin-left:2rem; + cursor: pointer; + border-radius: 0.3rem; + border: none; + color: white; + font-weight: bold; + transition: background .2s; + background: #5e44f6; +} + +input[type=submit]:hover, +input[type=submit]:focus{ + background: #2c10c9; +} + + +.result{ + font-size: 3rem; + font-weight: bold; + position: absolute !important; + left: 50%; + transform: translateX(-50%); + bottom: -10rem; + color : #f53277; + +} + +.calculator label{ + position: absolute; + left: 21px; + top: -6px; + padding: 0 0.5rem; + background: #f6f6f6 +} + +@media screen and (max-width:600px) { + .calculator{ + flex-direction:column; + } + input[type=submit]{ + width: 100%; + margin: 30px 0 0 0; + } + .operator{ + + margin: 1rem 0; + } + } \ No newline at end of file