form
HTML5이후로 action을 작성하지 않아도 된다.
GET 방식과 POST방식이 있다.

====================
input : file

form에 enctype : multipart/form-data 를 무조건 추가.
=> 
form의 method = 무조건 post.
=> contents 를 주소로 보낼 수 없음

HTMLInputElement.files 속성은 선택한 파일(File) 목록을 FileList 객체로 반환합니다.

FileList는 배열처럼 행동하므로, 
length 속성을 사용해 현재 선택한 파일의 수를 알 수 있습니다.

name
파일 이름.
lastModified
파일을 마지막으로 수정한 시각을 나타내는 숫자. UNIX 표준시(1970년 1월 1일 자정)으로부터 지난 시간을 밀리초 단위로 나타낸 값입니다.
lastModifiedDate 
파일을 마지막으로 수정한 시각을 나타내는 Date 객체. 더 이상 사용하지 않아야 합니다. lastModified를 대신 사용하세요.
size
파일의 크기를 바이트 단위로 나타낸 값.
type
파일의 MIME 유형.
webkitRelativePath 
webkitdirectory 특성을 사용한 경우, 기준 디렉토리에 대한 파일의 상대적인 경로. 비표준 특성이므로 사용에 주의가 필요합니다.

accept 특성

반응형
<!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="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
<style>
    #drop_zone {
  border: 5px solid blue;
  width:  400px;
  height: 300px;
}
</style>
<body>
    <h1>How to Drag&Drop File Upload</h1>
    <form method="post" enctype="multipart/form-data">
        <input type="file" id="file" name="file" multiple >
        <div id="drop_zone" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);">
            <p id="drop_zone_item_name_list" class="text-center">파일을 이곳에 끌어다 놓아주세요</p>
        </div>
        <button type="button" onclick="checkForm()" class="btn btn-primary">submit</button>
    </form>
    
<script>
    const dropZone = document.querySelector('#drop_zone')
    let formData = new FormData()   // formData library

    // 들어왔을 때 배경 색 변경
    dropZone.addEventListener('dragover', () => {
        dropZone.style.backgroundColor = 'gray'
    })

    // 나갔을 때 배경 색 복원
    dropZone.addEventListener('dragleave', () => {
        dropZone.style.backgroundColor = 'white'
    })


    function dragOverHandler(ev) {
        console.log('File(s) in drop zone');

        // Prevent default behavior (Prevent file from being opened)
        ev.preventDefault();
    }

    function dropHandler(ev) {
        console.log('File(s) dropped');
        ev.preventDefault();

        if (ev.dataTransfer.items) {
            let drop_zone_item_name_list = document.querySelector('#drop_zone_item_name_list')
            drop_zone_item_name_list.innerHTML = ""

            
            for (let i = 0; i < ev.dataTransfer.items.length; i++) {
                // If dropped items aren't files, reject them
                if (ev.dataTransfer.items[i].kind === 'file') {
                    const file = ev.dataTransfer.items[i].getAsFile();
                    // console.log('... file[' + i + '].name = ' + file.name);
                    drop_zone_item_name_list.innerHTML += file.name + "<br>"    // 리스트에 출력
                    console.log(file)   
                    formData.append('files',file[i]) // formData 에 data 삽입
                }else{
                    console.log('it is not a file')
                }
            }
            console.log('file loop is end')
        } else {
            console.log('use interface')
            // Use DataTransfer interface to access the file(s)
            for (let i = 0; i < ev.dataTransfer.files.length; i++) {
            console.log('... file[' + i + '].name = ' + ev.dataTransfer.files[i].name);
            }
        }
        dropZone.style.backgroundColor = 'white'
    }

    function checkForm() {
        if(formData) {
            $.ajax({
                data: checkForm,
                method: 'post',
                dataType: false,

            })
            .success( console.log('no error'))
            .fail(console.log('fail'))
        }
    }
</script>



</body>
</html>

반응형

안녕하세요 상훈입니다.

JavascriptPromise에 대해 알아보겠습니다.

내용은 해당 영상을 참고하였습니다.

 

Promiseasync 까지 연결되어 사용하는 내용도 가능합니다.

하지만 이번에는 성공, then() 까지만 확인하도록 하겠습니다.

 

예시) 일반적인 함수 사용하기.

기본적으로 delay라는 함수가 있을 때, 인자로 seccallback을 받습니다. 

함수 내부에는 setTimeout을 이용하여 sec초 뒤에 callback을 출력하는 함수입니다. (시간을 띄울거예요!)

function delay(sec, callback) {
    setTimeout(() => {
        callback (new Date().toISOString())
    }, sec * 1000)
}
delay(1, (result) => {
    console.log(1, result)
})

 

그리고 delay함수를 1초 뒤result 함수로 출력하겠다! 선언하면, 1초 뒤에 

해당 내용 출력

해당 내용이 출력됩니다.

 

만약 이곳에서 여러 개delay함수를 사용하여 쓰고싶다!  이렇다면, 흔히 말하는 콜백지옥함수가 될겁니다.

delay(1, (result) => {
    console.log(1, result)

    delay(1, (result) => {
        console.log(2, result)

        delay(1, (result) => {
            console.log(3, result)

            delay(1, (result) => {
                console.log(4, result)

                delay(1, (result) => {
                    console.log(5, result)
                })
            })
        })
    })
})

결과

결과적으로 잘~ 작동합니다! 하지만, 만약 저 코드 양이 방대해진다면, 본인은 물론 다른 사람도 보다가 미쳐서 모니터를 주먹으로 칠 수도 있습니다.

그래서 나온것이 Promise() 입니다.


 

예시2) Promise() : 여러 개의 then() 사용하기

function delayP(sec) {	// 인자를 시간초만 받음
    return new Promise( ( resolve, reject ) => {    // Promise (성공, 실패) 선언
        setTimeout(() => {
            resolve (new Date().toISOString())  // resolve(성공)에 해당하는 항목
        }, sec * 1000)
    })
}

 

then()

delayP(1)
    .then((result)=> {  
        console.log(1, result)
        return delayP(1)    // delayP() 를 return 시켜 새로운 promise를 실행하는 것. then으로 이어 받을 수 있다.
    })
    .then((result) => { // 2번 째 then을 통해서 위의 첫번째 then이 실행된 이후에 실행. 즉, 1초 + 1초 에 실행된다.
        console.log(2, result)
    })

 Promise() .then() 을 사용하는 것의 장점은 더 말할 필요가 없이 보기가 쉽습니다. 

또한 구분지어서 코드를 작성하는데에도 문제가 없죠. 

출력 결과

 

 

하지만 만약 반환값(return)을 작성해주지 않는다면,

delayP(1)
    .then((result)=> {  
        console.log(1, result)
        return delayP(1)    // delayP() 를 return 시켜 새로운 promise를 실행하는 것. then으로 이어 받을 수 있다.
    })
    .then((result) => { // 2번 째 then을 통해서 위의 첫번째 then이 실행된 이후에 실행. 즉, 1초 + 1초 에 실행된다.
        console.log(2, result)
        // return이 없다. => 다음 result = undefined가 될 것이다.
        // return 'string or something' 하면 해당하는 내용이 바로 출력된다. 
            // => delay를 통해 해당 내용을 지연시키지 않았기 때문에.
    })
    .then((result) => { // 받은 return 값이 null 이기 때문에 undefined를 출력한다.
        console.log(3, result)  // 출력 내용 ( 3, undefined )
    })

2번째 then에서 return없습니다!

=> 3번째 delayP( null ) 이 들어갔다는 뜻입니다.

그렇기 때문에 출력되는 것은 ( 3, undefined ) 가 됩니다.

출력 결과

추가적으로 sec 라는 인자도 전달이 안되었기 때문
바로 세번째 then() 이 실행되어 3, result 가 출력되었습니다.

2, 3번째 then()을 보기쉽게 해보자면, 아래와 같습니다.

    .then((result) => {
        console.log(2, result)
        console.log(3, result)  
    })

물론 2번째 then true라는 전제조건이 존재하지만요.

 

이상으로 promise 기초에 대한 포스팅을 마치겠습니다.

감사합니다.

 

 

참고

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise

 

Promise - JavaScript | MDN

Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.

developer.mozilla.org

 

 

 

반응형

 

안녕하세요 상훈입니다.

이 글을 PHP에 올려야할지 javascript에 올려야할지 고민을 1초 정도 했고 자바스크립트 기반이기 때문에 자바스크립트에 게시하게 되었습니다.

해당 과정은  [  select-box의 한 항목을 선택하면, 그 아래의 select-box가 활성화되면서 해당되는 리스트를 출력  ]  합니다.

Ajaxphp에 호출을 하면, php의 데이터베이스에서 데이터를 출력하여 배열에 담고,
담은 배열을 json endcode하여 출력하는 값을 json 형식으로 받아, 파싱하여 출력하는 것입니다.

 

 

1. javascript(ajax) (제이쿼리 필요합니다! [ cdn 링크 ] )
2. php

 

[ jQuery ] jQuery 제이쿼리 CDN 링크 공유

안녕하세요 상훈입니다. 자바스크립트 - 제이쿼리의 cdn을 공유합니다. 해당 코드 한줄을 내에 넣어줍니다.

code-hoon.tistory.com

 

HTML

<select id="name" onchange="selectItem()" name="name">
   <option value="" selected>아이템 리스트들</option>
   <option value="item01" >아이템 리스트1</option>
   <option value="item02" >아이템 리스트2</option>
   <option value="item03" >아이템 리스트3</option>
</select>
<select id="item_name">
   <option value="">선택해주세요</option>
</select>

 

이러한 html 요소들이 존재합니다.

onchange() 기능을 이용해 js에서 감지할 수 있도록 함수로 선언해주었습니다.

좌측에 select-box와 우측에 빈 select-box

 

리스트 요소 중 하나를 선택하면 해당되는 2번째 select-box에 값을 출력해줍니다. [ 데이터베이스 이용 ]

JAVASCRIPT  -  아래에서 상세히 설명

<script>
  function selectItem(value){
      any_name = document.querySelector('#name').value
      
      $.ajax({
        url: "getItemList.php",
        method: "POST",
        data: { any_name: any_name }
      })
      .done(
      	(result) => {
      		if(result === ''){
      			const item_name = document.querySelector('#item_name')
      			while(item_name.hasChildNodes() ){
      				item_name.removeChild(item_name.firstChild)
      			}
      			$('#item_name').append('<option value="">' + '선택해주세요 ' + '</option>');	
      		}else{
      			const item_name = jQuery.parseJSON(result)
      			i = 0
      			$.each(item_name, function(){
      				$('#item_name').append('<option value="' + item_name[i] + '">' + item_name[i] + '</option>');
      				i++
      			});
      		}
      	}
      )
      .fail( () => { alert('다시 시도해주세요.') })
  }
</script>

 

ajax 기본 틀

클릭시 복사할 수 있는 페이지로 이동(새창)

 

PHP [getItemList.php]

<?php
// 
if($any_name = $_POST['any_name'] ){
    
    //database 연동
    include '../db.php'; 
    
    //sql 작성
    $sql = "select item_name from 테이블 where 컬럼명 = '$any_name' ";
    $result = mysqli_query($conn, $sql);
    
	// 빈 배열 $array[]에 $row['item_name'] 넣어주기
    while($row = mysqli_fetch_assoc($result)){
        $array[] = $row['item_name'];
    }

	// json 객체로 변환하여 echo
    echo json_encode($array, JSON_UNESCAPED_UNICODE);

    
}else{
    echo ""; // 만약 선택하지 않았을 때 반환하는 값 : null
}

 


처음부터 보자면, 

1. name 이라는 id 를 가진 요소의 을 가져온다. ( 첫번째 select-box에서 선택한 요소 )

2. ajax를 이용하여 데이터를 송신한다. 

  [ 목적지 : url, 
    방식 : method(get, post) , 
    송신할 요소 (parameter) : data  ] 

 

3. php 에서 데이터를 출력하고 json 객체 출력해주기
   -> 주석으로 충분히 설명을 했다고 생각합니다.

 

4. javascript 에서 .done 부분

 

if영역(return null)else영역(return json)은 각기 다른 결과를 나타냅니다. 

else영역(return json)부터 보자면, 
1. item_name이라는 상수에 JSON을 파싱한 결과값(result)을 담습니다.
2. jQuery의 each함수를 사용하여, item_name을 반복해줍니다.
3. 각각 가지고 있는 item_name의 개수에 따라 결과에 추가 리스트의 개수가 달라집니다.

이와 같이 값이 호출되었습니다.

if영역(return null) 에서는 추가했던 option제거해주는 역할을 합니다.
 (혹은 이 내용을 기본값으로 하는 것도 좋을것같군요. 기본적으로 속을 비워주고, option을 채워주는 방식으로요.)

 


평소 ajax를 잘 사용하지 않아 해당 내용을 작성하는데에 조금 헤맸습니다.

이번 기회로인해 공부 잘하고 갑니다. ㅎㅎ

 

 

참고

 

jQuery.ajax() | jQuery API Documentation

Description: Perform an asynchronous HTTP (Ajax) request. The $.ajax() function underlies all Ajax requests sent by jQuery. It is often unnecessary to directly call this function, as several higher-level alternatives like $.get() and .load() are available

api.jquery.com

 

 

[자바스크립트] 모든 자식 엘레멘트 삭제하기 (Remove all children)

[Javascript] Removing all children using DOM * HTML로 프로그래밍하다보면 모든 자식 노드를 삭제해야하는 경우가 생긴다 그럴때 사용하면 되는 간단한 팁이다. var cell = document.getElementById("cell"); w..

unikys.tistory.com

 

이상입니다.

 

반응형

안녕하세요 상훈입니다.

$.ajax({
   url: ' ' ,
   method: ' ' ,
   data: {   },
   erorr: (  ) => {  },
   success: (  ) => {  }
})

이랬던 ajax가 변경되었습니다.

 

$.ajax({
   url: ' ' ,
   method: ' ' ,
   data: {  } ,
})
.done (  )
.fail (  )

 

참고 바랍니다.

 

 

jQuery.ajax() | jQuery API Documentation

Description: Perform an asynchronous HTTP (Ajax) request. The $.ajax() function underlies all Ajax requests sent by jQuery. It is often unnecessary to directly call this function, as several higher-level alternatives like $.get() and .load() are available

api.jquery.com

 

반응형

안녕하세요 상훈입니다.

Html, Css, Javascript 로 로딩 화면을 만드는 방법에 대해 포스팅하겠습니다.

BootStrap 을 이용하여 공통 클래스를 지정하였고. 일부분은 직접 작성하였습니다.

이미지를 클릭하시면 부트스트랩으로 이동합니다.

html

<div id="loader">
    <div class="spinner-border text-info position-absolute top-50 start-50" role="status">
        <span class="visually-hidden">Loading...</span>
    </div>
</div>

Css

#loader {
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    position: fixed;
    display: block;
    opacity: 0.8;
    background: rgb(156, 154, 154);
    z-index: 99;
    text-align: center;
}

#loader>div {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 100;
}

 

Javascript

$(window).on('load', function () {
    $('#loader').hide();
})

 - 제이쿼리를 사용할 수 있게 해야합니다.

  제이쿼리 cdn 적용하는 법 ↓

 

[ jQuery ] jQuery 제이쿼리 CDN 링크 공유

안녕하세요 상훈입니다. 자바스크립트 - 제이쿼리의 cdn을 공유합니다. 해당 코드 한줄을 내에 넣어줍니다.

code-hoon.tistory.com

 

  BootStrap cdn 적용하는 법 ↓

 

 

[ BootStrap ] 부트스트랩 cdn 적용하는 방법

안녕하세요 상훈입니다. 프론트엔드 부트스트랩 프레임워크를 사용하고 싶을때, cdn으로 class와 id에 대한 javascript, css를 적용하는 방법을 포스팅하겠습니다. 아래의 링크를 복사하여 head 태그 안

code-hoon.tistory.com

 

이상입니다.

반응형

안녕하세요 상훈입니다.

자바스크립트 - 제이쿼리의 cdn을 공유합니다.

 

해당 코드 한줄을 <head> </head> 내에 넣어줍니다.

<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>

 

제이쿼리를 넣은 head 태그 예시

 

 

jQuery cdn link - 클릭시 해당 주소로 이동.

반응형

안녕하세요 상훈입니다.

드림코딩 앨런님의 강의로 자바스크립트를 이용하여 짧고 간단한 쇼핑 웹앱을 구현하도록 해보겠습니다.

결과 화면

 

index.html

<!DOCTYPE html>
<html lang="ko">
<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">
  <link rel="stylesheet" href="style.css">
  <script src="src/main.js" defer></script>
  <title>Document</title>
</head>
<body>
  <!--Logo-->
  <img src="img/logo.png" alt="Logo" class="logo">

  <!--Buttons-->
  <div class="buttons">
    <button class="btn">
      <img src="img/blue_t.png" alt="blue tshirts" class="imgBtn" data-key="type" data-value="tshirt" />
    </button>
    <button class="btn">
      <img src="img/blue_p.png" alt="blue pants" class="imgBtn" data-key="type" data-value="pants" />
    </button>
    <button class="btn">
      <img src="img/blue_s.png" alt="blue skirt" class="imgBtn" data-key="type" data-value="skirt" />
    </button>
    <button class="btn" class="btn colorBtn blue"  data-key="color" data-value="blue">Blue</button>
    <button class="btn" class="btn colorBtn yellow" data-key="color" data-value="yellow">Yellow</button>
    <button class="btn" class="btn colorBtn pink" data-key="color" data-value="pink">Pink</button>
  </div>
  <!--Items-->
  <ul class="items"></ul>
</body>
</html>

 

 

main.js

// Fetch the items from the JSON file
function loadItems() {
    return fetch('data/data.json')
    .then(response => response.json())
    .then(json => json.items)
}

// update the list with the given items
function displayItems(items) {
    const container = document.querySelector('.items')
    container.innerHTML = items.map(item => createHTMLString(item)).join('')
}

// Create html list item from the given data item
function createHTMLString (item) {
    return `
        <li class="item">
            <img src="img/${item.image}" alt="${item.type}" class="item__thumbnail">
            <span class="item__description">${item.gender}, ${item.size}</span>
        </li>
    `
}

function onButtonClick (event, items) {
    const dataset = event.target.dataset
    const key = dataset.key
    const value = dataset.value

    if(key == null || value == null){
        return ;
    }

    // updateItems(items, key, value)

    const filtered = items.filter(item => item[key] === value)
    displayItems(filtered)
}

function updateItems(items, key, value) {
    items.forEach(item => {
        if(item.dataset[key] === value) {
            item.classList.remove('invisiable')
        }else{
            item.classList.add('invisable')
        }
    });
}


function setEventListeners (items) {
    const logo = document.querySelector('.logo')
    const buttons = document.querySelector('.buttons')
    logo.addEventListener("click", () => displayItems(items) )
    buttons.addEventListener("click", event => onButtonClick(event, items))
}


// main
loadItems() 
    .then(items => {
        displayItems(items)
        setEventListeners(items)
    })
    .catch(console.log)

 

 

style.css

:root {
  /* color */
  --color-black: #3f454d;
  --color-white: #ffffff;
  --color-blue: #3b88c3;
  --color-yellow: #fbbe28;
  --color-pink: #fd7f84;
  --color-light-grey: #dfdfdf;

  /* size */
  --base-space: 8px;
  --size-button: 60px;
  --size-border: 4px;
  --size-thumbnail: 50px;
  --font-size: 18px;

  /* animation */
  --animation-duration: 300ms;
}

body {
  height:100vh;
  background-color: var(--color-black);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.logo {
  cursor: pointer;
  transition: transform var(--animation-duration) ease;
}

.btn {
  background-color: transparent;
  border: none;
  outline: none;
  cursor: pointer;
  transition: transform var(--animation-duration) ease;
  margin-right: var(--base-space);
}

.btn:hover,
.logo:hover {
  transform: scale(1.1);
}

.buttons {
  display: flex;
  align-items: center;
}

.imgBtn {
  width: var(--size-button);
  height:var(--size-button);
}

.colorBtn {
  font-size: var(--font-size);
  padding: calc(var(--base-space) * 2);
  border-radius: var(--size-border);
}

.blue {
  background-color: var(--color-blue);
}

.yellow {
  background-color: var(--color-yellow);
}

.pink {
  background-color: var(--color-pink);
}

.items {
  width: 60%;
  height: 60%;
  list-style: none;
  padding-left:0;
  overflow-y: scroll;
}

.item {
  background-color: var(--color-white);
  display: flex;
  align-items: center;
  padding: var(--base-space);
  margin-bottom: var(--base-space);
}

.item__thumbnail {
  width: var(--size-thumbnail);
  height: var(--size-thumbnail);
}

.item__description {
  margin-left: var(--base-space);
  font-size: var(--font-size);
}

 

디렉터리 구조

디렉터리 구조는 다음과 같습니다. 강의 영상에서 제공한 project 자체를 import 시켰습니다.

이미지, json 등의 파일은 모두 구비되었습니다.

 

강의 진행이 되면서 간단하다 간단하다 하셨는데, 전혀 간단하게 느껴지지 않았습니다. ㅠㅠ

자바스크립트의 filter, map 등등 몇가지 라이브러리를 사용하셨었는데, 

저같은 웹린이한테는 어렵다고 느껴졌어요...

눈물..

나는 감자다! I'm annoied talking potatoooooooo!!!!

 

반응형

+ Recent posts