27일 수업이어서 플리커이미지검색.html에 작성
검색어 작성 후 클릭하면 해당 검색으로 이동하게
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="text" id="txtSch" value=""><button onclick="fSch()">검색</button>
<hr>
<div id="disp"></div>
<script>
// 27일 수업 이어서
// URL 상수(검색어만 변하면 되니까)
const preURL = "https://www.flickr.com/services/feeds/photos_public.gne?tags=";
const postURL = "&format=json";
// 정적 element는 전역변수로 두어야 찾은 걸 또 찾는 반복적 낭비작업이 없다!
const txtSch = document.querySelector("#txtSch");
const myDisp = document.querySelector('#disp');
// 검색 버튼 눌렀을 때
const fSch = function(){
let schURL = `${preURL}${txtSch.value}${postURL}`; // 플리커 URL 완성!
// 한번 실행하면 URL이 끝나기때문에 다시 사용하기 위해서는 만들어서 넣어줘야 한다
let scrTag = document.createElement("script"); // 스크립트 태그 생성
scrTag.src = schURL;
// 이후 문서에 붙여주어야 한다.
// head와 body는 문서에 1개만 있어야 하기때문에 따로 재선언 하지않고 다시 사용 가능
document.head.appendChild(scrTag);
}
// 호출되는 함수를 미리 만들어 둔다 , 그래야 호출 되니까
const jsonFlickrFeed = function(pData){
// alert("호출되나?");
console.log(pData);
myDisp.innerHTML = ""; // $("").empty() 또는 $("").html("") -> 검색할 때마다 사이트를 초기화 하기위해
let recvItems = pData.items;
for(let i = 0 ; i < recvItems.length ; i++){
let item = recvItems[i];
// 이미지 생성
let myImg = document.createElement("img");
myImg.src = item.media.m;
myDisp.appendChild(myImg); // 이렇게 해야 눈에 보인다!
// console.log(item.media.m);
}
}
/*
이런식으로 데이터를 주는것을 JSONP라 부른다 JSON PADDING(함수사이에 매개변수로 데이터를 준다)
CROSS-ORIGIN 제약사항에서 자유로움 , 하지만 서비스 하는 쪽에서 이런식의 서비스를 지원해주어야만 사용가능!
*/
</script>
<script src="https://www.flickr.com/services/feeds/photos_public.gne?tags=hamster&format=json"></script>
</body>
</html>
DOM search 메소드는 함수 안에다 작성? 밖에다 작성? 어느것이 더 좋은가?
페이지안에서 변하지 않는 것은(정적요소) 전역 변수로 밖에다 작성 해두어야 성능상으로 이점이 있다
함수 안에 작성하면 실행시 매번 새로 다시 검색한다
-> 정적 element는 전역변수로 두어야 찾은 걸 또 찾는 반복적 낭비작업이 없다.
이후 검색할 때마다 head사이에 스크립트 태그가 추가되는 것을 확인 가능(console.log)
ajax cross origin확인
이벤트.html생성
이벤트는 비동기적 처리이다
이벤트 등록법 3가지?
1.인라인 이벤트 - 디버그가 편하다, 동적 사용시 많이 사용, 매개변수 사용 안할시 this를 하나씩 작성 해주면 편리하다.
태그안에 this를 작성하면 this는 해당 태그객체를 가리킨다
2. onclick 속성에 함수를 연결
3. eventListener에 등록
<!DOCTYPE html>
<meta charset="UTF-8">
<body>
<h1>이벤트</h1>
<!-- inline 이벤트 등록 , 디버깅에 유리 , 디자이너가 싫어한다?-->
<button onclick="fClick(this)">눌러봐</button><br>
<button id="btn2">버튼2</button><br>
<div style="border:1px solid black" onclick="fCk()">
<span>나를 눌러줘</span>
</div>
</body>
<script>
const fCk = function(){
console.log(event.target); // 이벤트를 발생시킨 애를 가리킴
}
const myBtn2 = document.querySelector("#btn2");
// 이벤트 등록법 3개
const fClick = function(pThis){
console.log(pThis , "1번 inline 이벤트");
myBtn2.addEventListener("click",function(){ // jQuery의 on("이벤트명" , 함수)에 해당!
alert("3번 등록법 - 1을 가져다 붙여본다");
// 클릭한 만큼 추가되기 때문에 이후 버튼2 클릭시 1번을 클릭한 만큼 실행된다
});
};
/*
// 등록법2 , 재정의 한것이 이전것을 덮어버린다
myBtn2.onclick = function(){
alert("2번 , onclick속성에 함수를 연결");
};
myBtn2.onclick = function(){
alert("이전것을 덮어버린다");
};
// 등록법3 -> 계속해서 추가된다(권장방식)
myBtn2.addEventListener("click",function(){ // jQuery의 on("이벤트명" , 함수)에 해당!
alert("3번째 등록법- 1")
});
myBtn2.addEventListener("click",function(){
alert("3번째 등록법- 2")
});
*/
</script>
event.target -> 이벤트를 발생시킨 애를 가리킨다
나를눌러줘 div박스 클릭시 -> console.log 두가지가 출력가능한데 교묘하게 누르면 div가 나온다..
span , div둘다 출력된다
하지만 항상 div를 받고싶다면 아래처럼 작성하면 된다
const fCk = function(){
// console.log(event.target); // 이벤트를 발생시킨 애를 가리킴
console.log(event.currentTarget) // 이벤트를 등록시킨 애
}
이벤트2.html 생성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#grandma {
width:300px;
height:300px;
border:3px solid black;
}
#mom {
position: relative;
left:30px; top:30px;
width:150px;
height:150px;
border:3px solid pink;
}
#me {
position: relative;
left:30px; top:30px;
width:50px;
height:50px;
border:3px solid magenta
}
</style>
</head>
<body>
<div id="grandma" onclick="fGrand()">할머니
<div id="mom" onclick="fMom()">어머니
<div id="me" onclick="fMe()">나</div>
</div>
</div>
<script>
// 이벤트 버블링, 나에게 생긴 일이 부모에게 전달됨!
const fGrand=function(){
alert("이건 할머니");
}
const fMom=function(){
alert("이건 어머니");
}
const fMe=function(){
alert("이건 나")
}
</script>
</body>
</html>
이벤트 버블링을 막는다 -> 이벤트 캡쳐링 : event.stopPropagation , preventDefault (이벤트객체 기본동작 방지)
이벤트3.html 생성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<a href="https://naver.com" onclick="fMove()">네이버</a>
<script>
const fMove = function(){
alert("보이니?");
}
</script>
</body>
</html>
a태그 -> 클릭이벤트를 주지않아도 클릭이 가능하다 -> default Bulit-in기능
default built-in기능을 막기 위해 event.preventDefault 사용
const fMove = function(){
event.preventDefault(); // default built-in막기
//event.stopPropagation();
alert("보이니?");
}
preventDefault를 자주 사용 하는 곳? -> 폼태그 전송에서?
preventDefault , stopPropagation 자주사용하니 반드시 잘 알아둬야 한다.
form.html 생성
form태그는 body에 몇번 사용가능한가? -> 제한없음
하지만 form안에 form을 사용하면 안된다!! -> 코드가 길어지다오면 잘 보이지 않게된다
form action의 default값 -> 주소표시줄에 있는 값이 디폴트값이다
form메소드는 get , post 두가지이고 ajax는 자주쓰는 메소드 4개(get,post, put,delete)와 header , trace이외에 더 있다..
get조회 , post 생성 , put 수정, delete 삭제 -> Rest-ful 방식이라고 부른다
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<!-- form을 모르면 폼이 나지 않는다? ... -->
<!-- 몇번을 써도 되지만 form안에 from을 쓰면 안된다!! -->
<!-- form의 메소드는 get과 post 2개 , ajax는? get, post, put , delete, header , trace... -->
<!-- get조회 , post 생성 , put 수정, delete 삭제 , restful 방식이라고 부른다 -->
<form action="주소표시줄에 있는 값이 디폴트" method="get">
</form>
<script>
// URL 인코딩 디코딩
// escape unescape
// encodeURI decodeURI
// encodeURIComponent decodeURIComponent
let testStr = "hello test";
alert(encodeURIComponent(testStr));
</script>
</body>
</html>
get , post의 차이?(엽서(get)와 편지(post)라고 생각)
get -> url에 파라미터를 같이 넘긴다 , 엽서라 내용이 보인다
post -> url에 파라미터를 숨겨서 넘긴다
영어는 encoding을 하지 않는다?!
<script>
let testStr = "hello test";
alert(encodeURIComponent(testStr));
// 실행후 결과확인해보기 아래위 둘다
let testStr = "hello 한글";
alert(encodeURIComponent(testStr));
// 아래 작성 후 실행/결과 확인
let testStr = "hello 한글";
let encodeStr = encodeURIComponent(testStr);
alert(decodeURIComponent(encodeStr)); // 원래 모습으로
</script>
form태그 사용법은 정확하게 알고있어야..
<form action="주소표시줄에 있는 값이 디폴트"
method="get" enctype="application/x-www-form-urlencoded">
이름<input type="text" name="myName" value="사람"><br>
별명<input type="text" name="myAlias" value="뭐지"><br>
<button>전송</button> <!-- form태그 사이에 button태그 사용시 주의 -->
</form>
?name=value&name=value -> 쿼리스트링이라고 부름
id와 name값을 같이 주는데 , 같이줘도 문제없는 이유? id값은 서버로 넘어가지 않는다(name이 서버로 넘어간다)
버튼태그는 default값이 button이지만 폼사이에 들어가면 submit으로 동작한다(자동으로)
전송을 하지않고 싶으면 아래와같이 type을 직접 지정 해줘야함
<button>전송</button>
<!-- form태그 사이에 button태그 사용시 주의! 폼태그안에서 위처럼 작성시 submit으로 작동 -->
<button type="button">전송</button>
<!-- form태그 사이에 button태그 사용시 주의 -->
form 접근하는 방법? id를 선언해도 되고 forms[0] , forms[1] , ..이런식으로도 접근 가능
<body>
<!-- form을 모르면 폼이 나지 않는다? ... -->
<!-- form은 body안에 몇번을 써도 되지만 form안에 from을 쓰면 안된다!! -->
<!-- form의 메소드는 get과 post 2개, ajax는? get, post, put , delete, header , trace... -->
<!-- get조회 , post 생성 , put 수정, delete 삭제 , restful 방식이라고 부른다 -->
<!-- ?name=value&name=value -> queryString -->
<form action="" method="get" enctype="application/x-www-form-urlencoded">
이름<input type="text" name="myName" id="myName" value="사람"><br>
별명<input type="text" name="myAlias" id="myAlias" value="뭐지"><br>
<button type="submit">전송</button> <!-- form태그 사이에 button태그 사용시 주의 -->
</form>
<form action=""
method="get" enctype="application/x-www-form-urlencoded">
이름<input type="text" name="myName" id="myName" value="사람"><br>
별명<input type="text" name="myAlias" id="myAlias" value="뭐지"><br>
<button type="submit">전송</button> <!-- form태그 사이에 button태그 사용시 주의 -->
</form>
<form action=""
method="get" enctype="application/x-www-form-urlencoded">
이름<input type="text" name="myName" id="myName" value="사람"><br>
별명<input type="text" name="myAlias" id="myAlias" value="뭐지"><br>
<button type="submit">전송</button> <!-- form태그 사이에 button태그 사용시 주의 -->
</form>
<script>
// form 접근법
document.forms[2].myName.value = "따라치기힘드네";
</script>
유사배열은 배열의 속성을 가지지만 JS에서 제공하는 배열 메소드를 사용할 수 없다
<script>
const myForm2 = document.forms[2];
myForm2.myName.value="화이팅";
const elems = myForm2.elements; // elements에는 사용자 입력태그만 담김
// 이걸 이용해서 jQuery serialize 메소드를 만들 수 있다
var serStr="";
for(let i = 0 ; i< elems.length; i++){
console.log("체크 : " , elems[i].name, elems[i].value); // 유사배열 , 배열의 속성을 가진다
serStr += elems[i].name + "=" + elems[i].value + "&";
}
serStr += serStr.substring(0 , serStr.length-2);
// alert(serStr); // queryString
</script>
자바스크립트가 시작된 계기? 서버의 체크부하를 줄이기 위해서
사용자 입력의 유효성을 체크하기 위해서 만들어졌다(당시 vbscript도 있었다)
onsubmit ="return false" -> 절대 전송 불가(전송직전에 발생하는 이벤트)
onsubmit ="return true" -> 전송가능
return fchk()
const fchk=function(){
if(!document.forms[2].myAlias.value){
alert("값을 쓰지 않았다면")
document.forms[2].myAlias.focus(); // 커서를 해당 텍스트로 이동
return false;
} else {
return true;
}
}
위와같이 전송 여부를 함수로도 지정 가능 , 초기엔 저런식의 코드가 많이 사용 되었다
<form action=""
method="get" enctype="application/x-www-form-urlencoded">
이름<input type="text" name="myName" id="myName" value="사람" required pattern="010-[0-9]{4}-[0-9]{4}"><br>
별명<input type="text" name="myAlias" id="myAlias" value="뭐지" required><br>
<button type="submit">전송</button> <!-- form태그 사이에 button태그 사용시 주의 -->
<button type="button" onclick="mySubmit()">전송2</button>
</form>
나중엔 위와 같이 required(필수), pattern(정규식)을 사용해서도 가능(유효성체크)
제공하는것을 사용해도 좋지만 필요하다면 직접 만들어서 사용,
Ajax로 전송시 위처럼 button 선언 후 아래와 같이 함수 선언
const mySubmit = function(){
document.forms[1].submit(); // 직접전송!
}
전송2 버튼 누르면 체크되지 않고 그냥 전송된다 아래처럼 작성시 좋지 않음..쓸데 없이 코드가 낭비 경우가 발생
<button type="submit">전송</button> <!-- form태그 사이에 button태그 사용시 주의 -->
<script>
const mySubmit = function(){
document.forms[1].submit(); // 직접전송!
}
</script>
그래서 아래와 같이 사용하면 체크기능은 그대로 사용하고 , 전송은 막고 , 최종적으로 Ajax 처리가능
(내장기능을 막고싶을때)
const myForm1 = document.forms[1];
// 체크 기능은 그대로 쓰면서 , 전송은 막고 , 최종적으로 Ajax처리
myForm1.addEventListener("submit",function(){
event.preventDefault(); // form의 전송기능(built-in) 막기
alert("여기서 체크 기능은 그대로 쓰면서");
alert("전송은 막고")
/*
여기서 Ajax를 사용하게된다
*/
alert("최종적으로 Ajax처리한다");
});
볼튕기기.html 생성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#myBall {
transform: ;
position:absolute;
left: 100px;
width:60px;
height:60px;
border:1px solid black;
background-image: url("https://newsimg.sedaily.com/2023/05/13/29PK9BJYBL_2.jpg");
background-size:cover;
border-radius: 50%; /* 50%주면 원형*/
}
</style>
</head>
<body>
<div id="myBall" style="left:0px"></div>
<script>
const myBall = document.querySelector("#myBall");
// 화면 넓이와 화면 높이 alert(window.innerWidth); alert(window.innerHeight);
// 스크립트를 이용해서 left값 초기화
if(!myBall.style.left){ // 현재 값이 지정되어 있지 않다면
myBall.style.left = "0px"; // 초기화
}
const rightEnd = window.innerWidth;
let mvHor = 50; // 수평 움직임
const fMove = function(){
// alert(parseInt(myBall.style.left));
myBall.style.left = parseInt(myBall.style.left) + mvHor + "px"; //?
let ballLeft = parseInt(myBall.style.left);
let ballRight = ballLeft + 60;
// 오른쪽 || 왼쪽에 부딪히면 방향반대로
if(ballRight >= rightEnd || ballLeft <= 0){
// alert("충돌");
mvHor = -mvHor; // 산술부호를 이용해서 방향전환
// return;
}
setTimeout(fMove , 50); // 재귀호출
}
fMove();
</script>
</body>
</html>
저장, 실행 후 확인
transform : rotate(45deg) -> 이미지를 45도 회전시킨다
스크립트로 계속해서 이미지를 돌려보기
let mvHor = 10; // 수평 움직임
let rotGak = 0; // 각도
const fMove = function(){
rotGak = rotGak + 10;
myBall.style.transform = "rotateZ(" + rotGak + "deg)";
// alert(parseInt(myBall.style.left));
myBall.style.left = parseInt(myBall.style.left) + mvHor + "px"; //?
let ballLeft = parseInt(myBall.style.left);
let ballRight = ballLeft + 60;
// 오른쪽 || 왼쪽에 부딪히면 방향반대로
if(ballRight >= rightEnd || ballLeft <= 0){
// alert("충돌");
mvHor = -mvHor; // 산술부호를 이용해서 방향전환
// return;
}
setTimeout(fMove , 50); // 재귀호출
}
수직움직임 추가하기
<script>
const myBall = document.querySelector("#myBall");
// 화면 넓이와 화면 높이 alert(window.innerWidth); alert(window.innerHeight);
// 스크립트를 이용해서 left값 초기화
if(!myBall.style.left){ // 현재 값이 지정되어 있지 않다면
myBall.style.left = "0px"; // 초기화
myBall.style.top = "0px"; //
}
const rightEnd = window.innerWidth;
const bottomEnd = window.innerHeight;
let mvHor = 5; // 수평 움직임
let mvVer = 5; // 수직 움직임
let rotGak = 0; // 각도
const fMove = function(){
rotGak = rotGak + 10;
myBall.style.transform = "rotateY(" + rotGak + "deg)";
// alert(parseInt(myBall.style.left));
myBall.style.left = parseInt(myBall.style.left) + mvHor + "px"; //?
myBall.style.top = parseInt(myBall.style.top) + mvVer + "px"; //?
let ballLeft = parseInt(myBall.style.left);
let ballRight = ballLeft + 60;
let ballTop = parseInt(myBall.style.top);
let ballBottom = ballTop + 60;
// 오른쪽 || 왼쪽에 부딪히면 방향반대로
if(ballRight >= rightEnd || ballLeft <= 0){
// alert("충돌확인");
mvHor = -mvHor; // 산술부호를 이용해서 방향전환
myBall.style.transform = "skewY(45deg)";
// return;
}
if(ballBottom >= bottomEnd || ballTop <= 0){
mvVer = -mvVer;
myBall.style.transform = "skewX(45deg)";
}
setTimeout(fMove , 50); // 재귀호출
}
fMove();
</script>