안녕하세요 VanillaJS를 통해서 특정 작업을 하기전에 페이지 관련 내용들을 작성하여야 합니다.


(포스팅이 조금 늦은감이 있지만 ㅜ 주말까지 일을 하다보니.... )


index.html 이죠!!  제작되고있는 


전체 코드는  아래에 있습니다. (github) 에 올려놓고 있죠 후훗 


reactStudy/myVaniilaJS 에 있습니다.


VanillaJS 개요


https://ipex.tistory.com/224


그래서 오늘은 페이지의 메인이 되는 


index.html 을 작성하려고 합니다.


index.html


우선 해당 메인 페이지 의 작성은 프론트엔드 체크리스트 라는 사이트를 통해서 작성 하였습니다.


해당은 선언문입니다.


<!doctype html>

자칫 태그로 잘못 아실수 있지만 태그는 아니고 해당 HTML 이 몇 버전으로 작성되었다! 라고 브라우저가 알수 있도록 선언해주는 선언문 입니다.  doctype은 문서의 가장 첫번째 에 오게 됩니다.


MDN 에서는 doctype을 이와같이 설명합니다.


" HTML 에서 문서 타입은  '필수' 이며 **preamble 이다.해당 선언은 브라우저가 렌더링시 **"쿼크 모드(quirks mode)" 로 전환하는 것을 방지한다.  즉 <!DOCTYPE html> 은 일부 사양과 호환되지 않는 다른 렌더링 모드를 사용하는 대신 브라우저가 관련 사양을 따르는데 최선을 다한다."


또한 브라우저에서는 doctype을 확인할수 있도록 API 로 지원 하고있습니다.


doctype = document.doctype;
  • doctype is a read-only property.

[IE 11 에서의 document.doctype]

[Chrome 에서의 document.doctype]




doctype에 따라서 html 버전을 다르게 갈수있습니다. doctype에 대해서는 

해당 블로그에 설명이 너무 잘되어있어 링크로 대체 하도록 하겠습니다~

http://aboooks.tistory.com/40


HTML 버전 종류 



HTML 2.0 (RFC1866 규격) - 1995년 11월 24일 

HTML 3.2 (W3C 권고안)   - 1997년 1월

HTML 4.0  (W3C 권고안)  - 1997년 12월

HTML 4.0  (W3C 권고안)  - 1998년 4월

HTML 4.01 (W3C 권고안)  - 1999년 12월


XHTML 1.0 (W3C 권고안)  - 2000년 1월 26일

XHTML 1.1 (W3C 권고안)  - 2000년 1월 26일

XHTML 2.0 (W3C 권고안)  - 2000년 1월 26일 (사라짐)


HTML 5   - 2012 발표

HTML 5   - 2014년 10월 28일 표준안 확정

HTML 5.1 - 2016년 11월 01일 표준안 확정

HTML 5.2 - 2017년 12월 14일 표준안 확정

HTML 5.3 - 현재 진행 중


현재 모두는 HTML5로 해야되다보니 HTML5는 따로 조사해보시면 될 것 같습니다!


**preamble

preamble (프리앰블) : 비트 동기 또는 프레임 동기 등을 위하여 프레임 단위에서 각 프레임의 맨 앞에  붙이는 영역 (HTML에선 어떤식의 렌더링이 될지 알려주고 약속 하는 작업을 뜻하는 것으로 보입니다.)



 **"쿼크 모드(quirks mode)" 



<!DOCTYPE html>을 선언하는 이유 중 브라우저가 쿼크모드가 되지 않기 위해서라고 되어있는데요 

quirks mode (비표준 모드) : 


우선 왜 있을 까 ?? 라는 생각부터 하게 되었는데요 현재의 브라우저(HTML5)에서는 W3C 웹표준을 많이 따르기 위해 많은 브라우저들이 노력하고 있습니다. 그렇기 때문에 HTML5을 기준으로 돌아갈수 있도록 doctype을 지원하고 개발자들 역시 그에 맞게 화면을 구성하고있는데


"오래된 페이지" 와의 호환성을 제공하기 위해 모든 브라우저는 이 "quirks Mode"를 지원하게 됩니다. 

(이또한 IE에서 많이 발생합니다. 이슈가)


현재라면 HTML5와 CSS3을 기준으로  계속 작성해 나가시면 될 것 으로 보입니다.


참고 하였던 사이트 ( 정말 유용 했습니다. )


1. Front-End-Checklist 

프론트엔드 개발자들이 가져야할 체크리스트를 해주는 사이트입니다.

정말 유용해서 두번 놀랐네요 (아직 모르는게 많다는 것도 깨닫게 해줬습니다.)


2. Free favicon web Site

파비콘을 무료로 제공하는 사이트입니다 (유료도 구매가 가능합니다.)

https://www.iconfinder.com/icon-sets/featured/free/5


3. favicon Convert Web Site 

2번에서 제공된 파비콘을 파비콘 아이콘으로 변경해주는 사이트입니다.

https://converticon.com/


> 설정은 16 x 16 에서 256 x 256 까지 전부 체크하시고  Save As 하시면 됩니다.




이제 index.html 의 !doctype html  선언이 끝났습니다.



■ html 태그 속성 지정 ( lang , dir )



<!-- 페이지 내의 언어 속성 부여 -->
<!-- 페이지 내의 글자 방향 속성 부여 -->
<!-- rtl : right to left-->
<html lang="ko" dir="ltr">


rtl  ltr 인데요 페이지 내에서의  글자 방향 속성 부여인데요 


접속자가 다른 지역 일 경우 글자 방향이 다르게 나타날수 있기 때문에 이에 대한 명시를 html 태그에 직접 해주셔야 합니다.!




■ meta 태그 



Describe metadata within an HTML document


HTML 문서 내의 메타 데이터를 설명 한다 라고 W3School 에는 명시되어있습니다. 


맞습니다. 제가 작성한 페이지 (HTML DOM) 에 있는 메타데이터를 설명하기 위한 태그입니다.


charset = 'utf-8'


<!-- 문자집합 선언 -->
<meta charset="utf-8"/>


제가 사용하는 페이지의 문자 집합은 utf-8 으로 지정합니다.


http-equiv , content 


<!-- Internet Explorer에게 최신의 렌더링 엔진을 사용 지시 -->
<meta http-equiv="x-ua-compatible" content="ie=edge"/>


IE 8 브라우저 부터 나타났던 호환성 보기에 대한 내용인데요  IE브라우저가 최신의 렌더링을 사용할수 있도록 지시합니다.


http-equiv의 경우 : HTTP 헤더의 이름을 값으로 가질수 있으며  같이 가질수 있는 content의 종류는


"content-security-policy"  ,"content-type" , "refresh", "set-cookie" 등이 있습니다. 자세한 사항은 MDN 참조


MDN : https://developer.mozilla.org/ko/docs/Web/HTML/Element/meta


name 


<!-- Meta Description -->
<meta name="author" content="jaeuk_lee"/>
<meta name="description" content="깍돌이 스터디 페이지입니다."/>
<meta name="front-end-study" content="front-QA "/>


문서 레벨의 메타데이터의 이름을 정의 하는 속성이 있습니다. 해당 속성은 content 에 담긴 값과 연관이 지어집니다.


author  : 해당 문서의 작성자 


description : 페이지의 내용에 대한 짧고 정확한 요약을 담음 (FireFox나 오페라 의 경우 이를 즐겨찾기 페이지의 기본 설명으로 사용)


application-name : 웹 페이지 내에서 실행될 어플리케이션의 이름을 지정합니다. 


generator  : 페이지를 생성한 소프트웨어의 식별자


keyword : 콤마(',') 로 구분된 페이지의 내용과 관련된 단어를 담음


referrer : 문서에서 전송된 요청에 첨부된 HTTP 헤더의 참조를 제어 ( 해당 내용은 MDN 참조 )


** 해당 내용중 name="referrer"의 경우 document.wirte 또는 appendChild로 동적 삽입시 참조자의  작동을 예측 불가능 (no-referer 적용)


// 메타 데이터를 담는 다른 요소들도 있습니다.

** base head link style title 


css 로딩 (JS보다 항상 우선적으로 로딩이 될수 있도록 합니다.)


<!-- css는 무조건 js보다 먼저 로딩이 되어야 한다. -->
<link rel="stylesheet" type="text/css" href="./lib/css/normalize.css"/>
<link rel="stylesheet" type="text/css" href="./lib/css/index.css"/>


CSS 는 JS보다 먼저 로딩 되어야 한다 !!


해당 문구를 보고 아 그냥 CSS가 JS보다 먼저 로딩이 되어야 한다 라는 생각을 가지고 쓰는거보다


왜? CSS가 JS보다 먼저 로딩이 되어야 하는가에 대해 알고 작성하게되면


페이지를 작성하게 되었을 때 여러 가지 도움이 됩니다. ( 성능 적인 이슈 등 등 )


이거에 대해 도움이 되었던 페이지를 링크 합니다.


// Naver D2 브라우저는 어떻게 동작 하는가?

https://d2.naver.com/helloworld/59361


가장 무난한 WebKit 브라우저에 동작 과정을 보자면 








HTML 파서를 통해서 HTML 을 파싱 후 -> DOM 트리 


CSS파서를 통해 CSS을 파싱 후 -> CSS 규칙을 생성 


두 작업이 끝나야 렌더트리를 구축하고 화면을 그리기 시작 하게됩니다.


하지만 해당 도중 에 script 태그를 만난 다면?






DOM 파싱됐고 CSS 파서가 작동하게 되는데 여기서 멈춰버리는 현상이 발생합니다.  모든 파싱이 끝나게 되면 지연(async) 모드의 스크립트 에 대한 파싱을 하게 되며

문서 상태는 "완료" 후 "로드" 이벤트 (ex : window.onload) 가 발생하게 됩니다. 


HTML5에서는 해당 의 작업을 위해서 비동기 Script 로딩을 위해서 defer 와 async 라는 속성을 제공합니다. (이외에도 여러가지가있습니다. )


https://developer.mozilla.org/ko/docs/Web/HTML/Element/script  -> Script 태그 


간단하게 알아 보자면 


async :  해당 스크립트를 비동기적으로 실행 

defer :  브라우저의 ㅣDOMContnetLoaded 이벤트 발생전에 작동되어야 하는 스크립트 


** 하지만 2개의 경우는 inline 으로 작성시에는 동작하지 않습니다. 예를 들면 <script aysnc > -> XXX 동작 안됩니다.  JS로 사용시에만 해당됩니다.


그렇기 때문에 Inline으로 태그를 직접 작성하는 경우는 script 태그가 head 상단에 오면 안됩니다.

JS 예 

var fullPath = 'fullPath';
var _script = document.createElement('script');
_script.setAttribute('src',fullPath);
_script.async = true;

document.body.appendChild(_script);
// or
document.body.insertBefore(_script,document.body.lastChild);


해당과 같이 async 에 true를 주었을 때 비동기로 로딩이 되게됩니다. (이에 대해서는 따로 포스팅)


위의 내용을 정리하자면


CSS의 위치는???


문서를 파싱해서 DOM Tree을 만들 때 CSS가 없으면 렌더링을 할수가 없기 때문에  CSS를 가장 빨리 읽을수 있게 합니다. 그렇기 때문에 적합한 위치는


head 태그 사이에 위에 놓는 것입니다.  브라우저 인터프리터에서는 html 파일을 위에서 아래로 읽기 때문입니다.


그럼 CSS를  head 의 가장 맨앞에 놓고 Script 태그를 놓아서 JS를 로딩 시켜도 되지않을까?? -> 위에도 설명 이 되어있지만 Link 태그와 다르게 Script 태그의 경우 파싱 도중 만나게 


되면 파싱 작업을 멈추고 JS를 로드하게 됩니다. 그렇기 때문에 JS파일이 커진다면 사용자 입장에선 로딩 되는 형태로 보여지기 때문에 좋지 않은 결과를 (UX UI )를 


가져올수 있게 됩니다.


혹은 JS가 먼저 실행되어 적용이 되지 않는 형태가 될수도있습니다.( Ex: body 를 그리지 않았는데 DOM 컨트롤을 할 경우 -> undefined 에러 발생 ) 


그렇기 때문에 JS를 로드하는 Script의 경우는


body의 맨 마지막에 위치합니다.


<body>

<!-- do Something -->
<script src="./myLogic.js"></script>
</body>


이렇게 된다면 head태그에 있는 css들이 우선 로딩 된 후 파서들이 바디를 다 그린 후에 -> script 태그를 만나면서


해당 스크립트를 로딩하게 됩니다.


필요한 스크립트들은 해당 스크립트안에서 전부 로딩 시켜주는 형태로 작성을 할려고 합니다.


현재까지 만들어진 페이지의 코드를 보시면


<footer>
<div>
<span class="pages_desc">
ⓒ Gdl Blog Page
</span>
</div>
</footer>
</div><!-- app-root-->
<script src="./lib/gdl.js"> </script>
</body>

</html>



최하단에 gdl.js를 로딩 합니다.


해당 gdl.js에서는


function initialize(){
document.addEventListener("DOMContentLoaded", function() {
console.warn('Windows DOM ContentedLoaded');
gdlUtilModuleLoading();
setTimeout(function(){
gdlOtherModuleLoading();
},100);
// gdlOtherModuleLoading();
});
return{
}
}


보시는 것처럼 UtilModule을 로딩 후


다른 모듈을 로딩합니다.

function gdlOtherModuleLoading(){
var arr = ['gdlAjax','tempEvent'];
// 나머지 모듈 비동기로드
// arr.reduce(function(prev,curr,index,arr){
// Util.include(curr+'.js');
// },0);

// 현재는 동기로드
arr.reduce(function(prev,curr,index,arr){
Util.include({
path:curr+'.js',
jsfileName:curr,
async:false,
onload : function(){
console.warn('임시 테스트 코드 온로드 확인 ',tt);
}
});
},0);


}


보시면 Util.include라는 API(?) 를 사용하였는데요 이거는 제가 따로 함수로 빼놓았습니다.


Util.include는 


Util.include = function(path,configs){
try{
if(typeof path==='object' && typeof configs ==='undefined'){
var configs = path;
path = configs.path;
if(typeof path==='undefined')
throw new Error('path is Undefined');
}

var async =configs!==undefined ?
(configs.async!==undefined ?
configs.async : true) : true;
var pathArr = path.replace(/\.js/gi,'').split('/');
var fullPath = Util.basePath+pathArr.join('/')+'.js';
var jsfileName = configs!==undefined?
(configs.jsfileName !==undefined ?
configs.jsfileName : path) :
path;
var scriptTags = document.createElement('script');
scriptTags.setAttribute('src',fullPath);
scriptTags.async = async;

var onload = configs!==undefined?
configs.onload :
'undefined';
if(typeof onload==='function'){
scriptTags.onload = function (){
onload(fullPath);
}
}
else {
scriptTags.onload = function(){
console.log('onLoad Script >> '+ fullPath);
}
};
document.body.insertBefore(scriptTags,document.body.lastChild);
}
catch(err){
console.error(err);
}
}


lib 형태를 만들고 싶어서 기본 base Path 에 include 할 js들은 gdl.js에서  지정하고 include 합니다.


현재는 동기적으로 하기 위해서 위에 initialize 에서 보시면  async:fale를 지정하였습니다.


해당 index.html 을 console.log에서 확인해보면




위의 코드에서 gdlAjax.js 와 tempEvent.js를  로딩합니다. 


async:false로 지정하였기 때문에 100번을 새로고침해도 같은 형태로 로딩이 됩니다.


테스트 해본결과 async:true 로 하게되면 5번에 1~2번 정도는 순서가 바뀝니다.(비동기 이기 때문)


다음시간에는 해당 페이지를 조금 꾸미고


Button 먼저 만들어 보도록 하겠습니다.


긴글 읽어주셔서 감사합니다!


안녕하세요 정말 오랜간만에 포스팅을 하는 것 같습니다.


ㅜㅜ 회사일이 너무 바쁘네요;;  주말에는 잠만 자구..


사실 이번 포스팅도 조금 억지 스러울 수 있는데요


당연히 포스팅한줄 알았지만


포스팅이 안되어있어서 포스팅하게 되었습니다.


JavaScript를 통한 싱글톤 인스턴스 생성인데요  


Prototype의 경우


Instance = (function(){
function Instance(name){
this.eventObj = {
                "key":"value"
}   

}
// new를 하지 않으면 애초에 생성 불가
Instance.prototype.In = function(module,eventListener){
// this.eventObj 가능
        console.log(this.eventObj);
}
Instance._In = function(module,eventListener){
// this.eventObj 불가능
        console.log(this.eventObj); // undefined
        console.log(eventObj); // ReferenceError : eventObj is not defined
}
    return Instance;

})();


와 같이 this로 객체를 사용하기위해선 모두다 Prototype을 해주어야 합니다.


Instance = (function(){
function Instance(name){
this.eventObj = {
                "key":"value"
}   
}
Instance.prototype.In = function(module,eventListener){
// this.eventObj 가능
        console.log(this.eventObj); // {key : "value" }
}
// _In 은 애초에 사용 불가
Instance._In = function(module,eventListener){
// this.eventObj 불가능
        console.log(this.eventObj);
        console.log(eventObj);
}
    return new Instance;

})();


또한   단순히 Instance로 하여서


var test = new Instance() 로 한다고 하여도


협업을 한다고 가정 하였을 때  저는 


A.js 에서 var test = new Instance(); 하였는데


다른 QA분이 


B.js 에서 var test = new Instance(); 하게되면 


중앙관리가 되지 않습니다. 그렇다보니 싱글톤 패턴을 사용하게 됩니다.(인스턴스는 1개) 


이런 경우는 Prototype을 사용할 필요가 없습니다. 어차피 1개의 인스턴스만 사용될거니간요


테스트 해야 하는 케이스 중 2건 입니다.


//  

onLoad   

(  제품이 최초 실행되는 시점에 발생하는 onLoad 콜백 )


onBeforeLoad

 ( onLoad 전에 실행되는 onBeforeLoad 콜백 )


//


EventListener를 테스트해야 합니다. 해당의 리스너들은 호출이 되었을때 flag형태로 가지게 되는데 


1번 호출 시 true


2번 이상 호출시 false 입니다.


해당에 대한 내용을 확인 할수 있도록 싱글톤 패턴을 사용합니다.



var flag = (function(){
    'use strict'
    var instance;
    
    var topEventObj = {
        "APP":{
        },
        "DOM":{
        }
    }
    function _addEventProperties(obj){
        if(typeof obj !=='object'){
            return;
        }
        // 값 추가
        Object.defineProperty(
            topEventObj[obj.module],
            obj.eventListener,{
                value:true,
                writable:true,
                configurable:true,
                enumerable:true
            }
        )
    }
    function In(module,eventListener){
        if(typeof module ==='undefined' || typeof eventListener ==='undefined'){return;}
        var obj = changeProperties(module,eventListener);
        !!topEventObj[obj.module].hasOwnProperty(obj.eventListener) ?
                (topEventObj[obj.module][obj.eventListener] = false) :
                _addEventProperties(obj);
    }
    function Out(module,eventListener){
        
        if(typeof module ==='undefined' || typeof eventListener ==='undefined'){return;}
        var obj = changeProperties(module,eventListener);
        return !!topEventObj[obj.module].hasOwnProperty(obj.eventListener) ?
                topEventObj[obj.module][obj.eventListener] :
                false;
    }

    function changeProperties(module,eventListener){
        return {
            module:module.toUpperCase(),
            eventListener:eventListener.toUpperCase()
        }   
    }
    
    function initialize(){
            return {
                In:In,
                Out:Out,
            }
    }
    return {
            getInstance:function(){
                    if(!instance){
                        instance = initialize();
                    }
                return instance;
            }
    }
    
})().getInstance();



사용법은 다음과 같습니다.


JS-USE category 이기 때문에  JS에서


IIFE -> Singleton 과 JavaScript Object 에 대해서 다시 한번 설명하도록 하겠ㅅ브니다.



flag.In('app','onload');
flag.Out('app','onload'); // true

flag.In('app','onload');
flag.In('app','onload');
flag.Out('app','onload'); // false


().getInstance()를 통해서 생성과 동시에 flag에 인스턴스를 생성 하였습니다.


원래는 저부분이 빠지고


var test = flag.getInstnace(); 형태입니다.


이후에 var test2 = flag.getInstance로 하여도 이미 생성된 instance가 있기 때문에 새로 객체를 만들지 않습니다.


순서는 단순합니다.


In ->  module과 eventListener를 파라미터로 받습니다.


값에 정합성을 위하여 모든 파라미터를 toUpperCase()를 적용합니다.


var topEventObj = {
        "APP":{
        },
        "DOM":{
        }
    }


해당 객체를  가지고  테스트합니다.

** hasOwnProperty 를 통해서 해당 값이 있을경우는 해당 값을 false로 변경하고


** 없을 경우는 defineProperty 를 통해서 생성합니다.


포스팅을 뭔가 쉬지 않아야 한다는 느낌 때문에


억지로 쓴거 같긴한데 ㅜ


읽어 주셔서 감사합니다.








안녕하세요 오늘은 i태그 <i> 와 <span> 에 대해서 작성하려고 합니다.


태그공부가 다시 제대로 되어야 할거 같아서 작성하게 되었습니다. 네이티브 코드를 다루는 일을 한다면 좀 더 좋을텐데


아니다 보니 자꾸 까먹게 되는 것 같습니다.


i 태그 와 span 태그 에 작성에 앞서 mdn 등 공식 자료를 먼저 보는게 나을거같아요 


이거 먼저 가져 와보겠습니다.


자료는 역시 MDN!


The HTML <i> element represents a range of text that is set off from the normal text for some reason. Some examples include technical terms, foreign language phrases, or fictional character thoughts. It is typically displayed in italic type.


일반적으로는 이탤릭에 사용된다고 하며 어떠한 이유로든 일반 텍스트에서 벗어난 텍스트의 의미!


음...  기존에 (옛날 브라우저) 는 i를 이탤릭 전용으로만 사용하였지만 현재의 i태그는 해당의 의미로는 사용되지 않고


css를 통하여 특정 작업을 하는 형태로 진행되고 있다고 합니다.


i 태그 설정시 기본으로 font-style이 italic으로 들어온 모습




span 태그는


The HTML <span> element is a generic inline container for phrasing content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the class or id attributes), or because they share attribute values, such as lang. It should be used only when no other semantic element is appropriate. <span> is very much like a <div>element, but <div> is a block-level element whereas a <span> is an inline element.

요약을 하자면 span 태그는 아무 동작도 하지않는 inline 컨테이너 라고 합니다. 

> inline과  inline-block 및 block 에 대해서는 저 깍돌이가 예전에 작성한 적이 있습니다.

> display 형식이라고 보면되는데 그중 span 은 기본적으로 inline형태를 지닌다!    라고 볼수 있겠네요
inline display 에 대해 알면 되겠네용

대표적으로 inline 은 block 과 달리 100%를 차지하지 않기 떄문에

글사이에 색상을 넣는 용도로 쓰는 경우가 많은 것 같습니다.

[span 태그를 통한 색상 변화]








b태그가 기본적으로 굵게 해주기 때문에 b태그 안에 span 을 적었습니다.

<b>inline text in <span>b tag </span></b>
// 관련 css
span{
color: rgb(127, 204, 124);
}




번외


i 와 span 태그를 찾다 보니 i는 icon 의 i로 아이콘 쓸때 사용이 좋다 라는 많은 글들을 보았는데


컨테이너 형식을 가지는 span 이 조금 더 적합하다고 생각되며 부트스트랩 UI같은 플러그인도 최신버전에는 icon 을 


span 으로 사용한다고 합니다.


bootstrap UI Icon (공식홈)














안녕하세요 <script> 태그를 추가할때 동적 으로 추가 하는 방법 중 하나를 소개하고자 합니다.


JS - USE 포스팅에선 단순하게 코드 위주로 포스팅 하려고 하기 때문에


간단 설명과 


코드 첨부 합니다.


다음 Post 서비스를 cdn 으로 동적 추가 하는 코드 

var daumPostcdnURL = "http://dmaps.daum.net/map_js_init/postcode.v2.js?autoload=false";
		var daumPostCDNScript  = document.createElement('script');
		daumPostCDNScript.setAttribute('src',daumPostcdnURL);
		daumPostCDNScript.onload = function(){
				console.warn('daumPostCDN Script Load Success');
		}
		document.body.insertBefore(daumPostCDNScript,document.body.firstChild);


간단 설명 

1. cdn URL을 설정

 

2. document.createElement 를 통하여 스크립트 생성 


3. setAttribute 를 통하여 src에 해당 url지정


4. 로딩 확인을 위해 onload 콜백 실행 


5. document.body.insertBefore 를 통해 해당 스크립트를 바디 맨 앞에 추가 

안녕하세요 오늘은 CSS의 우선순위에 대해 작성해보려고 합니다.


작성할 생각이 없긴 했는데


업무하다 가 CSS 관련 우선순위 에 대한 테스트 파일을 만들게 된게 조금 아쉬워서


포스팅하게 되었습니다.



기본적으로 CSS 우선순위는  


1 순위 -> !important

2 순위 -> inline style attirbute ex:       <button style="background: red; color:white;"></button>

3 순위 -> id

4 순위 -> 없는 attribute가 있을 경우

5 순위 -> tag element



아래의 자료를 보면 어느정도 이해가 되실텐데요 



CSS order 

https://www.w3schools.com/css/css_howto.asp


오늘 포스팅할 내용은 우선순위가 같을 경우는 지정한 개수가 더 많은 css가 높은 우선순위를 지니게 되는데요


이점에 대해서 작성하려고 합니다.


우선 아래의 이미지를 보시면



 

기본적으로 화면은 이렇게 되어있습니다.

 

화면에 대한 태그는

 

 

이러한 형태의 구성을 지니고있습니다.

 

csstestArea -> dummyDiv   > 버튼들

 

각각 버튼에 css를 보시면 .btn 클래스와 .cssFirst .btn 클래스와 .cssSecond 클래스 형태로 붙어있습니다.

 

지정된 css는

 

 

이런형태로 지정이 되어 있습니다.

 

.btn .cssFirst는

 

.btn 의셀렉터를 통하여 기본적으로 지정이된 후에

 

.cssFirst가 입혀집니다.

 

가장 좌측에 있는 버튼의 색상이 변경되는 이유입니다.

 

이 상태에서 cssFirst를 선택자를 더늘려서 선택 해보겠습니다.

 

 

 

 

뒤에 선언됐으니까

 

겹쳐진거 아니냐 할수도있어서

 

위로 올려보면

 

 

 

결과는 이렇습니다.

 

전체 테스트 하였던 파일은 아래에 적어 놓겠습니다.


글 읽어 주셔서 감사합니다.



 

 

<!DOCTYPE html>
<html>
<head>

    <title> 테스트 </title>
    <meta charset="utf-8">
    
    <style>

*{
    box-sizing:border-box;
}
    .csstestArea{
        display:flex;
        flex-flow:row nowrap;
        justify-content:flex-start;
    
    }
    .csstestArea .btn{
        display:flex;
        padding:6px 12px;
        font-size:14px;
        font-weight:400;
        line-height:1.42857143;
        white-space:nowrap;
        text-align:center;
        width:100px;
        height:50px;
        margin:5px;
        vertical-align:middle;
        color: white;
        border:1px solid transparent;
        user-select:none;
        background-image:none;
        border-radius:4px;
        
        outline:0;
    }

    .csstestArea .dummyDiv .cssFirst{
        background-color:red;
    }

    .cssFirst{
        background-color:#CEFBC9;
    }
    

    .cssSecond{
        background-color:#FAF4C0;
    }

    .dummyDiv{
        display:inherit;
    }
    .csstestArea button:active{
        outline:0;
        background-color:#D4F4FA;
    }
    </style>
</head>
<body>
<div class="csstestArea">
    <div class="dummyDiv">
            <button type="button" class="btn cssFirst"></button>
            <button type="button" class="btn cssSecond"></button>
            <button type="button" class="btn"></button>
    </div>
</div>
</body>
</html>


넵 저번 포스팅에서 drag and drop 에 대해서 정말 간단하게만 작성 하였는데


drop까지는 못했던것 같습니다.


그 마무리 작업을 하도록 하겠습니다.


// 자바스크립트를 이용한 드래그 앤 드롭 1탄!

https://ipex.tistory.com/entry/JavaScript-USE-HTML5-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%93%9C%EB%9E%98%EA%B7%B8-%EC%95%A4-%EB%93%9C%EB%A1%AD-Drag-and-Drop-using-JavaScript-and-HTML5


우선 저번 코드에서 해줘야 할 작업이 있습니다.


객체를 이동할건데요 이동하기 위해서 객체의 최상단에 id값을 하나 주도록 하겠습니다.


<div class="dragtarget" id="newTargetID">
        <div class="dragInner" draggable="true" ondragstart="dragStart_(event)" ondrag="drag_(event)">
            Drag Target
        </div>
    </div>



자 새롭게 id를 추가하였구요


dragStart부분에서


해당 id값을 던지기로 합니다.


   function dragStart_(e){
                console.warn('drag Start');
            var parentNode = e.target.parentElement;
            e.dataTransfer.setDragImage(parentNode,0,0);    

            e.dataTransfer.setData('targetId',e.target.parentElement.id);

        }


event.dataTransfer에 있는 setData로 데이터를 set하고 drop에서 getData로 받아 와서 사용 가능합니다.


** 드래그 이벤트는 보라색 영역만 받기 때문에 전체 태그가 드래그 하기 위해서 parentElement.id로 부모의 id를 넘기도록 합니다. id도 부모에 설정 하였구요


그리고 dropzone에 droppable ="true"는 설정 된상태겠죠? drop 이벤트에


e.preventDefault() 추가와

해당 id값을 가져와서 dropzone에 붙이도록 하겠습니다.


   function drop_(e){
            console.warn("drop");
            e.preventDefault();
            var targetId = e.dataTransfer.getData('targetId');

// e.target ( 현재 dropzone 태그 )

// e.target.appendChild (해당 dropzone 태그에 )

// document.getElementById(targetId) 드래그 하였던 타겟 (setData로 id를 넘김)

// 을 붙이도록 합니다.

            e.target.appendChild(document.getElementById(targetId));
        }



이 작업이 완료 될 시






드롭시!




깔끔하게 드롭된 점이 확인되네요


미천한 글 읽어주셔서 감사합니다.~


전체 소스코드 


<!DOCTYPE html>
<html>
<head>

    <title> 드래그앤드롭 </title>
    <meta charset="utf-8">
    
    <style>
    .dragtarget{
        width:100px;
        height:100px;
        background-color:tomato;

    }
    .dragInner{
        width:inherit;
        height:30px;
        background-color:slateblue;

        color:white;
    }
    .dropzone{
        position:absolute;
        width:500px;
        height:500px;
        background-color:yellowgreen;

        left:300px;
        top:300px;
    }
    </style>
</head>
<body>
    <div class="dragtarget" id="newTargetID">
        <div class="dragInner" draggable="true" ondragstart="dragStart_(event)" ondrag="drag_(event)">
            Drag Target
        </div>
    </div>
    <div class ="dropzone" droppable="true" ondragover="dragOver_(event)" ondrop="drop_(event)"> Drop Zone </div>
<script>
        function dragStart_(e){
            console.warn('drag Start');
            var parentNode = e.target.parentElement;
            e.dataTransfer.setDragImage(parentNode,0,0);    
            e.dataTransfer.setData('targetId',e.target.parentElement.id);
        }
        function drag_(e){
            console.log("drag");
        }
        function dragOver_(e){
            e.preventDefault();
        }
        function drop_(e){
            var targetId = e.dataTransfer.getData('targetId');
            console.warn("drop");
            e.preventDefault();
            e.target.appendChild(document.getElementById(targetId));
        }
</script>
</body>
</html>


안녕하세요 정말 오랜만에 포스팅을 하는거 같습니다... 


회사일이 너무 바쁜것..


이번 포스팅에서는 HTML5 에서 제공하는 Drag and Drop 에 대해서 작성할 예정입니다.


물론 테스트 브라우저는 Chrome 입니다.


우선적으로 HTML5에 drag and drop 에 대한 mdn 주소입니다.


// HTML5 drag and drop MDN

https://developer.mozilla.org/ko/docs/Web/API/HTML_%EB%93%9C%EB%9E%98%EA%B7%B8_%EC%95%A4_%EB%93%9C%EB%A1%AD_API


우선 드래그를 하기 위한 target 데이터와  드롭을 할수 있는 드롭 존  2개를 만들어 보도록 하겠습니다.



자 이렇게 2개의 div를 만들었습니다. (HTML 코드는 볼수 있도록 아래에 적어 놓겠습니다.)


해당 Drag Target을 드래그하여 초록색 Drop Zone 에 넣을 겁니다.


일단 그냥 드래그를 해볼까요?


역시 안됩니다.


드래그하기 위해서는 draggable 속성을 true로 주어야 합니다.


그런데 여기서 특이점이 제가 dragtarget을 일부러 2개의영역으로 잡았습니다.


반반씩 있는 영역이 아니라 dragtarget이라는 영역 내부에 dragInner를  넣은 형태 입니다.


    <div class="dragtarget">
        <div class="dragInner">
         Drag Target
        </div>
    </div>


코드는 이와 같습니다.


이렇게 한 이유는 조금있다 알수 있습니다.


드래그포인트는 dragInner 에만 줄려고 합니다. 다른 영역은 드래그는 대부분 제목 표시줄에만 되는경우가 많으니까요


자 드래그를 해봅시다



드래그가 되긴 하는데 썸네일이 조금 맘에 안드네요 ( draggable이 dragInner에만 들어가있어서 해당 객체에 대한 썸네일만 제공됩니다.)


최대 root객체를 지정하여서 다 같이 나오게 하고 싶은데요 이부분을 처리 해주는 곳이 setDragImage입니다. (IE에선안됩니다. )


테스트용이기 때문에 div 태그 안에 inline 으로 ondragstart 함수를 하나 만들어 줍니다.(태그안에 ondragstart같이 넣는 방법은 좋은 방법은 아닙니다. 지금은 테스트용이기 때문에 이렇게 작성합니다.


> addEventListener('dragstart',dragStart,false); 와 같은 형식을 취하는게 더 좋습니다.


div class="dragtarget">
        <div class="dragInner" draggable="true" ondragstart="dragStart_(event)"
ondrag="drag_(event)">
            Drag Target
        </div>
    </div>

function dragStart_(e){
        console.warn('drag Start');
}
function drag_(e){
    console.log("drag");
}


와 같은 형태로 작성을 해줍니다.


잘 되는 점확인이  됩니다. 이제 썸네일 부터 바꿔 보겠습니다.

event로 들어오는 값을 이용해서 작성 합니다.


function dragStart_(e){
                console.warn('drag Start');
            var parentNode = e.target.parentElement;
            e.dataTransfer.setDragImage(parentNode,0,0);    
        }


setDragImage의 첫번째 인자로는 썸네일 을 받게되는데 


event.dataTransfer.setDragImage(image, xOffset, yOffset);

를 확인해보면 image를 dragInner가 아닌 부모의 값 전체를 선택하게 하고 오프셋 x와 y 를 0으로 주게되면 현재 마우스의 위치에서 바로 부모의 객체가 나타날것으로 보입니다.



짜잔 ㅎㅎ    부모의 객체를 그대로 썸네일 형태로 가져와서 사용하게 됩니다.


이제 드래그가 가능한 상태가 되었고 해당 객체를 Drop Zone 에넣어 줘야 되는데요 아무리 이동을 해도 넘어가지 않습니다.


드래그가 가능하기 위해서 draggable 속성을 주게 되는데 드롭도 마찬 가지입니다. droppable  이라는 속성이 필요합니다.

<div class ="dropzone" droppable="true"> Drop Zone </div>


dropzone 에도 추가 해줍니다. 


draggable  ondragstart , ondrag 가 짬뽕이였듯이

droppable  ondrop   , ondragover 가 짬뽕입니다.

    <div class ="dropzone" droppable="true" ondragover="dragOver_(event)"
ondrop="drop_(event)"> Drop Zone </div>


        function dragOver_(e){
            console.log('dragOver');
        }

        function drop_(e){
            console.log("drop");
        }



하고 드래그앤 드롭시 보면 drop 이 발생하지 않는 점을 확인 하실수 있습니다.



mdn 에 는 dragover시 drop 을 활성화 하기위한 2가지 방법을 제시하고있습니다.


<div ondragover="return false">
<div ondragover="event.preventDefault()">

Calling the preventDefault() method during both a dragenter and dragoverevent will indicate that a drop is allowed at that location. However, you will commonly wish to call the preventDefault() method only in certain situations, for example, only if a link is being dragged. 

저는 event.preventDefault 로 처리하였는데 대부분 이 방식대로 처리 한다고 합니다.


Drop 처리가 되는 점을 확인 하실 수 있습니다.


하지만  실제 설정한 target이 이동되지는 않았기 때문에 이 이동에 대한 내용을 다음 에 작성 하겠습니다.


감사합니다.


코드


<!DOCTYPE html>
<html>
<head>

    <title> 드래그앤드롭 </title>
    <meta charset="utf-8">
    
    <style>
    .dragtarget{
        width:100px;
        height:100px;
        background-color:tomato;

    }
    .dragInner{
        width:inherit;
        height:30px;
        background-color:slateblue;

        color:white;
    }
    .dropzone{
        position:absolute;
        width:500px;
        height:500px;
        background-color:yellowgreen;

        left:300px;
        top:300px;
    }
    </style>
</head>
<body>
    <div class="dragtarget">
        <div class="dragInner" draggable="true" ondragstart="dragStart_(event)" ondrag="drag_(event)">
            Drag Target
        </div>
    </div>



    <div class ="dropzone" droppable="true" ondragover="dragOver_(event)" ondrop="drop_(event)"> Drop Zone </div>
<script>
        function dragStart_(e){
                console.warn('drag Start');
            var parentNode = e.target.parentElement;
            e.dataTransfer.setDragImage(parentNode,0,0);    
        }
        function drag_(e){
            console.log("drag");
        }

        function dragOver_(e){
            e.preventDefault();
            console.log('dragOver');
            
        }

        function drop_(e){
            console.log("drop");
        }
</script>
</body>
</html>





안녕하세요 이번 flex에서는


container 속성에서 기존에 있던 direction 속성을 알아야 사용할수가 있는


속성인 justify-content 와 align-items 속성에 대해서 포스팅을 하려고합니다.


알아야 하는 이유는 


justify -content ( 가로축 - 중심축 )


align-items ( 세로축 - 교차축 )


이기 때문에 flex-direction : row,  row-reverse, column , column-reverse 의 속성을 알아야 현재 컨테이너에 어떤 


정렬을 넣어야 하는지 알수 있기 때문입니다. 


justify-content  

 

> 가로 축을 기준으로 좌우에 대한 정렬을 관장 합니다.

속성 나열은 아래와 같습니다.


flex-start (default)                 >>  요소들을 컨테이너의 왼쪽으로 정렬

flex-end >>   요소들을 컨테이너의 우측으로 정렬

center >> 요소들을 컨테이너의 중앙으로 정렬

space-between                 >> 요소들 사이에 동일한 간격을 둡니다.

space-around          >> 요소들 주위에 동일한 간격을 둡니다.

space-evenly(FireFox Only)         >> 첫번째로 오는 정렬 대상 전에 두개 의 인접한 정렬 대상 사이의 간격과

마지막 정렬 대상 이후의 간격이 같도록 항목이 분산 됩니다.


설명은 이와같고 가로 축 정렬이기 때문에

flex-flow 는 row nowrap 으로 진행하겠습니다.


start

end

center 는 아래의 사진과 같이 요소들의 시작 시점입니다.

 (처음에 할때 거꾸로 출력되는거 아닌가? 하고 헷갈렸습니다.. ㅜ)

거꾸로는 row-reverse를 써야하죠;;


이 3개의 속성은 그냥 해보면 바로 직관적으로 알수 있습니다.

space-between 과 space-around를 보죠


between 은 사이의 간격이 일정합니다.  (양쪽 끝을 붙일 상태에서 사이사이에 일정한 간격을 두기 위해선 좋네요)


around는 외부의 간격이 일정합니다. (맨 처음과 맨 끝은 좌우가 일정하진 않지만 끝과 끝은 일정하죠 )


space-evenly(FireFox Only) 의 경우는 around의 추가된점? 으로 around는 양쪽 끝으로 인해 외부 간격이 전부 일정하다고는 보기 힘들지만  space-evenly 를 이용하면 전부 똑같은 간격을 가질수 있습니다.




align-items

세로 축을 기준으로 정렬을 하게 됩니다.


flex-start          컨테이너의 최상단으로 정렬 합니다.

flex-end          컨테이너의 최하단으로 정렬합니다.

center                         컨테이너의 세로 축의 중앙으로 정렬 합니다.

baseline                      컨테이너의 시작위치에 정렬 합니다.

stretch(default)             컨테이너의 맞게  늘립니다.

직관적입니다. 위 아래 중앙 나머지 baseline과 stretch 에대해서 좀더 자세히 보기전에


직관적인 start end center 부터 보면



보시는 것처럼 매우 직관적이고 justify-content 와같이 좌 < - > 우 가 아닌 세로 축이기 때문에


위 


아래 기준으로 잡고 정렬 을 하게 됩니다.



baseline 과 stretch(Default)  을 보겠습니다.


???? flex-start 와 차이점이 없어 보입니다. 



baseline                      컨테이너의 시작위치에 정렬 합니다.

stretch(default)            컨테이너의 맞게  늘립니다.

라고 되어있는데 baseline과 stretch 의 확인을 해보겠습니다.

span 태그를 제가 보기 편하게 하기 위해서 

크기를 정확히 지정해 놓았기 때문에 발생한것으로 해당 에서만 제거하고 확인해보면


span 의 height 와 width 를 auto 로 준후 확인시



stretch 는 확인이 되었습니다. (자동으로 찰때 꽉찹니다.) 세로축 기준이기 때문에 세로로 꽉채워집니다.

(이 때문에 input  같은 버튼 생성시 width : auto 로주면 꽉차게 됩니다. flex-start로 줘야 합니다.)


자 이번엔 baseline을 확인해보겠습니다.


font-size를 바꾸고 비교해보았습니다. 위는 baseline이고 아래는 flex-start입니다.


그림판을 통해 직선으로 선을 그렸을때 baseline은 아래의 라인이 맞고 


아래의 flex-start는 조금 떠있는 모습이 보여집니다.




이로써 가로와 세로 축 정렬 방법에 대해 봤고


row와 column 을 통해서 방향을 가로로 할지 세로로 할지도 봤기 때문에 기본적인 Flex Box Model 에정렬은 한것 같습니다.


여기까지 해본 후에 는 FlexBox 개구리 테스트를 해보면 좋을거 같아서 링크를 남깁니다.


10번 깼습니다


// flexBox Froggy  게임  플렉스 박스 게임 

https://flexboxfroggy.com/#ko


[마지막 번 문제 24번]

해당 번호전까지는 아마 술술 풀릴거라 생각 됩니다.


24번도 뭐 금방 풀겠지만 잠깐 


보자면 이렇습니다. 이 개구리들을 여러가지 속성을 합쳐서 원래의 위치에 가져다 놔야 합니다.



일단 화면만 놓고 봤을땐 2- 5 로 되어있는데 7개의 개구리가 일자로 되어있기 때문에 줄바꿈이 필요해보입니다.


그리고 세로 방향으로 보이니 flex-wrap : wrap 과 flex-direction:column 이 필요할거같아서 두개를 합치면



음 좌우가 반대인거같아서 reverse를 줘야 할거같은데 column-reverse를 주게 되면 노랑개구리가 내려오고 빨간개구리도 내려올뿐 좌우가 변하진 않습니다. 


기존의 포스팅 했던 줄넘기기에 보면




// 줄넘기기 

http://ipex.tistory.com/entry/CSS3-flex-Box-flexwrap-%EC%A4%84-%EB%84%98%EA%B8%B0%EA%B8%B0-flexflow-%EB%B0%A9%ED%96%A5-%EC%A4%84-%EB%84%98%EA%B8%B0%EA%B8%B0?category=768582


wrap-reverse가 더 맞아 보입니다.


그런데 답칸이 4줄밖에 없기 때문에 flex-flow를 통하여 합쳐 주는것이 좋아보입니다.


flex-flow:column wrap-reverse;



그뒤로는 해보면 되겠죠?  : 정답 (드래그하세용) 


flex-flow:column-reverse wrap-reverse;

align-items:flex-end;

justify-content:center;

align-content:space-between;



특정 태그에 대한 이벤트 받는 형식을 막고 싶을때


예를 들면


input#testEvents:checked+label {


/*  do thing */


인데 do thing 에서 CSS3 애니메이션을 사용한다고 가정할때


ex)  transform: translateX(120%);


해당 애니메이션이 실행안되게 하고싶은데 CSS속성을 똑같이 하나 클롬을 떠서 (js)로 애니메이션만 제외하고 


이런건 너무 무식한 방법 같고 


찾다 보니 events를 받지 못하게 하는 방법이 있다고 해서 적용 해보았습니다.


답은 pointerEvents 



값으로는


auto


none


stroke /* SVG -only  */


fill  /* SVG -only  */





a[href="http://localhost"]{
       pointer-events:none;
}

dfdsfdfsdf

document.querySelector("input#runTag").style.pointerEvents="none";

이벤트를 동작하지 않게 하는 방식입니다.


이외의 속성들을 SVG 온니 이므로 mdn 참조 바랍니다.


안녕하세요 이번에는 flex에서 


flex-wrap ( 줄 넘기기 ) 와  기존에 포스팅 하였던 flex-direction 과 flex-wrap 을 한꺼번에 제어하는


flex-flow ( 방향과 줄넘기기 ) 에 대해서 작성 하려고 합니다.




flex-wrap 


  • nowrap (default)
  • wrap
  • wrap -reverse


  • flex-wrap 은 컨테이너의 크기보다 아이템들의 크기가 늘어났을 때의 어떻게 동작할 것 인가에 대한 속성 지정입니다.


    display: flex 인 flex에서는 flex-wrap으로 지정 합니다.




    1. nowrap (Default)


    flex-wrap을 지정하지 않은 경우는 기본이 nowrap 입니다. 그렇기 때문에 기본적으로 nowrap 은 위와같이 동작합니다


    박스안에 초록 아이템들이 위와같이 있는 상태에서 앞으로 더 추가 될 박스가 있을 경우  점선 박스의 위치로 붙게 됩니다.


    - 결과 



    2. wrap


    wrap으로 지정된 상태에서 노란 박스의 경우 width 가 고정되어있을 시 아래로 줄을 넘기게 됩니다.



    - 결과 화면




    height 를 고정으로 놓았을 경우의 wrap 결과 화면







    3. wrap - reverse

    위의 wrap 의 반대 로 줄을 넘기게 된다는 의미의 reverse입니다. wrap의 경우는 우측 아래로 넘기기 때문에


    reverse는 좌측 위로 넘기게 됩니다.




    - 결과 화면



    height 를 고정으로 놓았을 시의 결과 화면






    flex-flow


    flex-flow는 flex-direction || flex-wrap 형태로 작성되어지는 속성이며


    기본값으로는 row 와 nowrap 을 가집니다.


    맨위의 nowrap 이 direction 이 row이기 때문에


    해당 html 에서 flex-direction 과 flex-wrap 을 제거하고


    flex-flow : row nowrap; 으로 작성 하여 테스트 해보았습니다.


    flow-flow : flex-direction flex-wrap 형태만 기억하면 되겠네요


    flex-flow: row nowrap;


    의 형태로 사용됩니다.


    - 결과 화면











    + Recent posts