반응형
반응형

자바스크립트에서 이벤트가 동작되는 과정에는 두가지 방식이 있습니다.

 

기본적으로 이벤트 버블링으로 동작합니다.

📝이벤트 버블링

이벤트 버블링이란 하위 태그에서 이벤트가 발생할시 위에 태그로 전달하는 형태입니다.

 

이렇게 전달하면 이벤트가 전파되는데 밑에와 같은 코드가 있을 경우 Three → Two → One 순으로 누를시

Three 누르면 Three, Two, One이 출력이 됩니다.

Two 누르면 Two, One이 출력이 되고

One 누르면 One이 출력이 됩니다.

<!DOCTYPE html>
<head>

</head>



<body>
	<div class="one" id="one">
        one
		<div class="two" id="two">
            two 
			<div class="three" id="three">
                three
			</div>
		</div>
	</div>
</body>

<script>


var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
	});
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}
</script>

 

 

이렇게 동작하는 과정을 이벤트 버블링이라고 합니다.

 

 

 

📝이벤트 캡처

 

이벤트 캡처라는 방식도 존재합니다.

이벤트 캡처란 이벤트 버블링이랑 다르게 최상위 태그에서 해당 이벤트 태그로 전파합니다.

 

이벤트가 전파되는데 밑에와 같은 코드가 있을 경우 Three → Two → One 순으로 누를시

Three 누르면 One, Two, Three이 출력이 됩니다.

Two 누르면 Two, One이 출력이 되고

One 누르면 One이 출력이 됩니다.

* 이벤트 버블과 반대 순서로 작동

<!DOCTYPE html>
<head>

</head>

<body>
	<div class="one" id="one">
        one
		<div class="two" id="two">
            two 
			<div class="three" id="three">
                three
			</div>
		</div>
	</div>
</body>

<script>


var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
		capture: true // default 값은 false입니다.
	});
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}
</script>

 

 

위와 같은 걸 고려해서 만들기 귀찮거나 할 경우에는 event.stopPropagation()을 사용하면 됩니다.

아까랑 스크립트 코드가 다르지만 이것은 이벤트 버블링이 적용된 상태입니다.

event.stopPropagation() 을 사용할 경우 전파하지않고 해당 태그만 이벤트가 작동합니다.

<!DOCTYPE html>
<head>

</head>



<body>
	<div class="one" id="one" onclick="hello1()">
			one
		<div class="two" id="two" onclick="hello2()">
				two 
			<div class="three" id="three" onclick="hello3()">
					three
			</div>
		</div>
	</div>
</body>

<script>
    function hello1(){
        event.stopPropagation();
        console.log(event.currentTarget.className);
    }

    function hello2(){
        event.stopPropagation();
        console.log(event.currentTarget.className);
    }
    function hello3(){
        event.stopPropagation();
        console.log(event.currentTarget.className);
    }
</script>

 

 

 

 

 

 

📝이벤트 위임

지금까지 위에서 한 행위들은 이벤트 위임을 이해하기 위함입니다. 물론 내가 원하는 방식하고 다르게 동작하는 것에 대한 파악도 가능하지만요 이벤트 위임은 바닐라 JS로 웹 앱을 구현할 때 자주 사용하게 되는 코딩 패턴입니다. 하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어합니다.

 

<!DOCTYPE html>
<head>

</head>
<body>

<h1>오늘의 할 일</h1>
<ul class="itemList">
	<li>
		<input type="checkbox" id="item1">
		<label for="item1">이벤트 버블링 학습</label>
	</li>
	<li>
		<input type="checkbox" id="item2">
		<label for="item2">이벤트 캡쳐 학습</label>
	</li>
</ul>
</body>


<script>
var inputs = document.querySelectorAll('input');
inputs.forEach(function(input) {
	input.addEventListener('click', function(event) {
		alert('clicked');
	});
});
    
</script>

 

위에 코드는 체크박스 클릭시 Alert이 노출되는 형식으로 돌아갑니다.

여기에서 회원의 권한에 따라 보여지는 체크박스 수가 달라질 경우 추가된 체크박스에 이벤트 리스너를 또 추가해야 추가된 체크박스도 또한 위와 같이 동작하게 됩니다. 이러한 걸 이벤트 위임으로 간단하게 처리할 수 있습니다.

 

 

<!DOCTYPE html>
<head>

</head>
<body>

<h1>오늘의 할 일</h1>
<ul class="itemList">
	<li>
		<input class="item" type="checkbox" id="item1" >
		<label for="item1">이벤트 버블링 학습</label>
	</li>
	<li>
		<input class="item" type="checkbox" id="item2">
		<label for="item2">이벤트 캡처 학습</label>
	</li>
</ul>
</body>


<script>
let itemList = document.querySelector('.itemList');

itemList.addEventListener('click', function(event) {
	alert('clicked');
});


let createCheckBox = () => {

    let li = document.createElement('li');
    let input = document.createElement('input');
    let label = document.createElement('label');
    let labelText = document.createTextNode(' 이벤트 위임');

    input.setAttribute('type','checkbox');
    input.setAttribute('id','item3');
    label.setAttribute('for','item3');
    label.appendChild(labelText);
    
    li.appendChild(input);
    li.appendChild(label);
    itemList.appendChild(li);
}

createCheckBox();

</script>

 

 

label 해당 영역을 누른 경우 2번 호출되는데 클릭시 label이 input checkbox를 호출하면서 ul범위 안에 있기 때문에 alert이 한번 호출되고 1번 ul 자체를 클릭한 거이기 때문에 1번 이런식으로 호출된다. 

 

label을 다른 방식으로 처리하든가 분기처리를 하던가 하면 될 거 같다 (label 자체의 문제임)

 

생각해봤는데 이벤트 위임의 경우 ul태그가 크니까 ul태그안에 어딜 눌러도 ul에 적용되어있는 이벤트는 다 동작한다

직접 안 써봐서 모르겠는데 복잡하게 생각할 건 없는 거 같다.

 

 

 

출처 : https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/

반응형
반응형

앵커(Anchor) A태그를 의미한다.


A태그로 function 사용하는 방법은 3가지가 있습니다.
1. <a href="javascript:callHello();">javascript function</a>
<a href="javascript:function callHello(){alert("hello");} a();">javascript function</a> <!-- 위와 동일 -->

2. <a href="javascript:void(0);" onclick="callHello();">onclick function</a>

3. <a href="#" onclick="callHello();">call function</a>
href="#"을 해 놓으면 클릭시 이벤트 버블링으로 인해 anchor을 타서 브라우저 상단으로 이동합니다.
2번과 같은 방식또는 <a href="#;" onclick="callHello(); return false;">onclick function</a>와 같이 처리로
브라우저 상단으로 안 가게 가능합니다.

반응형
반응형
$.ajax({
    url: "http://127.0.0.1:8080/ocr_search/engine", // Generally use Controller URI
    type: "GET", // GET, POST
    data: {
        status : "200",
        id : "hello",
        shaAdminPw : "hhh",
        type : "f"
    },
    //async : false, // Async 
    success : (result) => console.log(result), //when you success, you can handle it
    fail : (error) => console.log(error), // when you fail, you can handle it
    complete : (finalResult) => console.log(finalResult) // it runs, whenever you fail or success
});

 

@RequestMapping(value = "/engine", method = RequestMethod.GET)
public void engine(EngineDto engineDto) {
	System.out.println(engineDto.getId()); // hello
}
public class EngineDto {

	private String status = "";
	private String id = "";
	private String shaAdminPw = "";
	private String type = "f";

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getShaAdminPw() {
		return shaAdminPw;
	}

	public void setShaAdminPw(String shaAdminPw) {
		this.shaAdminPw = shaAdminPw;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
}

해당 객체에 setter만 있으면 알아서 잘 data-binding 됩니다.

 

반응형
반응형
function drawRamPieChartAjax(){

	return new Promise((resolve,reject) =>{
	$.ajax({
		url: "pie-charat",
		type: 'GET',
		success: function(data) {
			initRamPieChart();

			let totalRamSize = data.total_ram;
			let freeRamSize = data.free_ram;
			let usedRamSize = totalRamSize - freeRamSize;

			drawRamPieChart(usedRamSize, freeRamSize);

			resolve("sucess");
		}, //success end
		error : function (error) {
			alert(error.status);       // 에러코드 
			alert(error.responseText); // Error 메시지 
		}, // error end
		complete : function (){
			alert("finally");
		}
	}); //ajax end	
	}); // promise end
}
반응형
반응형

앵커(Anchor) A태그를 의미한다.

 

- 방법 1
<a href="javascript:void(0)">링크기능무효화</a>
void(0)의 경우, () 안의 값이 숫자나 영문자 등등을 사용해도 문제는 없지만, 일반적으로 숫자 0을 사용합니다.

- 방법 2
<a href="# return false"> return false 로 링크 기능인 href가 수행시키지 않게 한다.

- 후기 
그냥 # 뒤에 아무거나 붙여도 기능 수행을 안시킨다 하지만 저렇게 return false 처럼 명시해두면 구분하기는 편할 거 같다.

반응형
반응형
function uuidv4() {
  return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  );
}
반응형
반응형
//이미지 미리보기 
function imagePreview() {
	 var filedata = document.getElementById("license_org_file");
	 var file;
	 var formdata = new FormData();
	 
	 file = filedata.files[0];
	 
	 var img = URL.createObjectURL(file); 
     // blob:http://localhost:8080/b9a326dd-8438-4e17-a0de-99c7e0158bbd
	 
     /** 파일 정보를 읽어 사진이 로컬에 있는 것처럼 보이게 한다. **/
     $("#imageView").attr("src", img); 
      
     return true;
     	 
}
<input style="display: inline-block; width:230px;" id=license_org_file class="form-control" type="file" placeholder="">
<img id=imageView  style="max-width: 100%; height: 50%;">
반응형
반응형
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script src="valina.js"></script>
    <!-- js 파일 용량이 크거나 용량이 큰 경우 화면이 나오는 데 까지 속도가 느리다.-->
    <!-- parsing HTML →  block(fetching js | executing js) → parsing HTML  -->

    <script async src="valina.js"></script>
    <!-- 비동기 처리로 js 다운 받는데 시간 절약을 할 수 있지만 아직 파싱중인데 중간에 멈춰버리거나
         해당 DOM 요소가 만들어지지 않았는데 그걸 가지고 조작하는 함수가 있는 경우 치명적이다. -->
    <!-- parsing HTML →→→→→→→→→ block (executing js)  → parsing HTML  -->
    <!--       |  fecthing js  |  -->

    <script defer src="valina.js"></script>
    <!-- 비동기 처리로 js 다운 받고 HTML 다 그려진 후에 js를 실행 시키기 때문에 비동기적으로 다운 시간 절약과
         async의 문제도 해결할 수 있다. (가장 추천) -->
    <!-- parsing HTML →→→→→→→→→→→→→→→→  block (executing js) -->
    <!--         |      fecthing js     |     -->

    
</head>
<body>
  
    
<script src="valina.js"></script>

<!-- 화면을 빨리 볼 수 있는 장점은 있지만 js로 구현한 이벤트 핸들러는 다운 받을 때까지 사용 불가 -->
<!-- parsing HTML →  NonBlock(fetching js | executing js) -->
</body>
</html>

출처 : 드림코딩

 

반응형
반응형

 

function setDatePicker(){
	
	$("input.start_date").datepicker({
		 dateFormat: 'yy-mm-dd' //달력 날짜 형태
		,showOtherMonths: true //빈 공간에 현재월의 앞뒤월의 날짜를 표시
		,showMonthAfterYear:true // 월- 년 순서가아닌 년도 - 월 순서
		,changeYear: true //option값 년 선택 가능
		,changeMonth: true //option값  월 선택 가능                
		,showOn: "both" //button:버튼을 표시하고,버튼을 눌러야만 달력 표시 ^ both:버튼을 표시하고,버튼을 누르거나 input을 클릭하면 달력 표시  
		,buttonImage: "http://jqueryui.com/resources/demos/datepicker/images/calendar.gif" //버튼 이미지 경로
		,buttonImageOnly: true //버튼 이미지만 깔끔하게 보이게함
		,buttonText: "선택" //버튼 호버 텍스트              
		,yearSuffix: "년" //달력의 년도 부분 뒤 텍스트
		,monthNamesShort: ['1월','2월','3월','4월','5월','6월','7월','8월','9월','10월','11월','12월'] //달력의 월 부분 텍스트
		,monthNames: ['1월','2월','3월','4월','5월','6월','7월','8월','9월','10월','11월','12월'] //달력의 월 부분 Tooltip
		,dayNamesMin: ['일','월','화','수','목','금','토'] //달력의 요일 텍스트
		,dayNames: ['일요일','월요일','화요일','수요일','목요일','금요일','토요일'] //달력의 요일 Tooltip
		,minDate: "-5Y" //최소 선택일자(-1D:하루전, -1M:한달전, -1Y:일년전)
		,maxDate: "+5y" //최대 선택일자(+1D:하루후, -1M:한달후, -1Y:일년후)  


	});
	$("input.end_date").datepicker({
		 dateFormat: 'yy-mm-dd' //달력 날짜 형태
		,showOtherMonths: true //빈 공간에 현재월의 앞뒤월의 날짜를 표시
		,showMonthAfterYear:true // 월- 년 순서가아닌 년도 - 월 순서
		,changeYear: true //option값 년 선택 가능
		,changeMonth: true //option값  월 선택 가능                
		,showOn: "both" //button:버튼을 표시하고,버튼을 눌러야만 달력 표시 ^ both:버튼을 표시하고,버튼을 누르거나 input을 클릭하면 달력 표시  
		,buttonImage: "http://jqueryui.com/resources/demos/datepicker/images/calendar.gif" //버튼 이미지 경로
		,buttonImageOnly: true //버튼 이미지만 깔끔하게 보이게함
		,buttonText: "선택" //버튼 호버 텍스트              
		,yearSuffix: "년" //달력의 년도 부분 뒤 텍스트
		,monthNamesShort: ['1월','2월','3월','4월','5월','6월','7월','8월','9월','10월','11월','12월'] //달력의 월 부분 텍스트
		,monthNames: ['1월','2월','3월','4월','5월','6월','7월','8월','9월','10월','11월','12월'] //달력의 월 부분 Tooltip
		,dayNamesMin: ['일','월','화','수','목','금','토'] //달력의 요일 텍스트
		,dayNames: ['일요일','월요일','화요일','수요일','목요일','금요일','토요일'] //달력의 요일 Tooltip
		,minDate: "-5Y" //최소 선택일자(-1D:하루전, -1M:한달전, -1Y:일년전)
		,maxDate: "+5y" //최대 선택일자(+1D:하루후, -1M:한달후, -1Y:일년후)  

	});

	$('.start_date').datepicker("option", "maxDate", new Date());
	$('.end_date').datepicker("option", "minDate", $(".start_date").val());
	$('.end_date').datepicker("option", "maxDate", new Date());

	$("#end_date").on("change", function() { // sel02 정렬순서
		$('.start_date').datepicker("option", "maxDate", $(".end_date").val());
		$('.end_date').datepicker("option", "minDate", $(".start_date").val());
		$('.end_date').datepicker("option", "maxDate", new Date());
	});

	$("#start_date").on("change", function() { // sel02 정렬순서
		$('.start_date').datepicker("option", "maxDate", $(".end_date").val());
		$('.end_date').datepicker("option", "minDate", $(".start_date").val());
		$('.end_date').datepicker("option", "maxDate", new Date());
	});

	// $('#start_date').datepicker('setDate', 'today'); //(-1D:하루전, -1M:한달전, -1Y:일년전), (+1D:하루후, -1M:한달후, -1Y:일년후)
	// $('#end_date').datepicker('setDate', 'today'); //(-1D:하루전, -1M:한달전, -1Y:일년전), (+1D:하루후, -1M:한달후, -1Y:일년후)       
	
}

$(document).ready(function() {
	setDatePicker();
})

date.js

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

    <script type="text/javascript" src="./date.js"></script>

</head>
<body>
    <div class="start">
        <div class="date_picker">
            <input class="start_date" type="text" id="start_date"
                name="start_date" />
        </div>
    </div>
    <div class="end">
        <div class="date_picker">
            <input class="end_date" type="text" id="end_date" name="end_date" />
        </div>
    </div>
</body>
</html>

datepicker.html

반응형