본문 바로가기
javascript

2024-02-28

by rewind 2024. 2. 28.

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>