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


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


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


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


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


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 를 통해서 생성합니다.


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


억지로 쓴거 같긴한데 ㅜ


읽어 주셔서 감사합니다.








안녕하세요 <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 를 통해 해당 스크립트를 바디 맨 앞에 추가 

넵 저번 포스팅에서 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>


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


예를 들면


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 참조 바랍니다.


자바스크립트의 배열 [ ] 의 경우에는


length 를 통하여 길이를 간단하고 손쉽게 가져 올 수 있습니다.


하지만 obj의 경우에는 length 를 지정하게 되면 undefined 가 나타납니다.


obj 의 경우 length 의 길이를 구하기 위해서는


Object.keys를 이용해야 합니다.


 

var objS = {name:"test",ttt:"NewTest",kim:"kim"};

console.log("obj.length : ",objS.length);
console.log("Object.keys Length : ",Object.keys(objS).length);

Object.keys에 대해 간단하게 적어 보면


Object.keys(obj)

obj -> 열거형 고유 속성이 반환될 개체


return Value -> 지정된 개체의 모든 나열형 속성들을 나타내는 문자열 배열

나열형 속성들을 나타낸다고 되어있다.


속성열 나열 테스트


var myObj = Object.create({}, {
  getFoo: {
    value: function () { return this.foo; }
  } 
});
myObj.foo  = 1;
myObj.foo2 = 2;
myObj.foo3 = 3;

console.log(myObj);
console.log(Object.keys(myObj)); 


결과

{foo: 1, foo2: 2, foo3: 3, getFoo: ƒ}

(3) ["foo", "foo2", "foo3"]


현재 접속한 브라우저를 확인 한다. 자세한 내용은 JS에서 다루고


해당 카테고리에서는 코드만 적어 놓으려고 합니다. 


간단하게 



var _browserState = 'unknown';


(function checkBrowser(){

var agent = navigator.userAgent.toLowerCase();

if(agent.indexOf("chrome")!=-1){_browserState="Chrome";}

else if(agent.indexOf("safari")!=-1){_browserState="safari";}

else if(agent.indexOf("firefox")!=-1){_browserState="firefox";}

else if(agent.indexOf("msie")!=-1 || agent.indexOf('trident')!=-1){_browserState="IE"}

for(let i=0;i<5;i++){ console.warn("connected Browser is "+_browserState);}


})();


// Extension Download reProduction Code 

var _downloadEx = function(filename,contents){

         if(_browserState.toLowerCase() ==='chrome'){

  var element = document.createElement('a');

  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(contents));

  element.setAttribute('download', filename);

  element.style.display = 'none';

  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);

}

//not in Chrome

else{

var a = document.createElement("a"),


    file = new Blob([contents], { type: "text/plain;charset=utf-8" });


    if (window.navigator.msSaveOrOpenBlob) // IE10+

        window.navigator.msSaveOrOpenBlob(file, filename);

    else { // Others

        var url = URL.createObjectURL(file);

        a.href = url;

        a.download = filename;

        document.body.appendChild(a);


        a.click();

        setTimeout(function () {

            document.body.removeChild(a);

            window.URL.revokeObjectURL(url);

      }, 0);

    }

}

}


+ Recent posts