[Jquery] Sortable(마우스 드래그 앤 드롭으로 리스트 정렬)


안녕하세요. 명월입니다.


이 글은 Jquery의 Sortable(마우스 드래그 앤 드롭으로 리스트 정렬)에 대한 글입니다.


많은 분들이 드래그 앤 드롭 기능을 사용한다고 하면 사실 이 Sortable를 찾는 게 많을 것입니다. 그냥 드래그 앤 드롭으로 레이 아웃만 움직이는 건.. 뭐 사양에 따라 사용하겠지만 가장 많이 사용되는 건 이거이지 않을까 싶습니다.

여러 개의 세로로 된 리스트를 만들어서 안의 아이템을 이리 저리 이동 가능하게 만드는 것입니다.

링크 - https://jqueryui.com/sortable/

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <!-- 부트스트랩 4.x를 사용한다. -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<style>
  /* 리스트 css */
  .column{
    border: 1px solid #cecece;
    padding-top: 10px;
    padding-bottom: 10px;
  }
  .container-fluid{
    margin-top: 20px;
  }
  .container-fluid .card{
    margin-left:auto;
    margin-right:auto;
  }
  /* 이동 타켓 */
  .card-placeholder {
    border: 1px dotted black;
    margin: 0 1em 1em 0;
    height: 50px;
    margin-left:auto;
    margin-right:auto;
    /* 노란색으로 표신되는 것이 주요 포인트 */
    background-color: yellow;
  }
  /* 마우스 포인터을 손가락으로 변경 */
  .card:not(.no-move) .card-header{
    cursor: pointer;
  }
</style>
<body>
  <div class="container-fluid">
    <div class="row">
      <!-- 세로 리스트 박스 -->
      <div class="col-4 column">
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-primary mb-3 no-move">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 1</h5>
            <p class="card-text">no-move</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-secondary mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 2</h5>
            <p class="card-text">card 2</p>
          </div>
        </div>
      </div>
      <!-- 세로 리스트 박스 -->
      <div class="col-4 column">
        <div class="card text-white bg-success mb-3 no-move">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 3</h5>
            <p class="card-text">no-move</p>
          </div>
        </div>
      </div>
      <!-- 세로 리스트 박스 -->
      <div class="col-4 column">
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-danger mb-3 no-move">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 4</h5>
            <p class="card-text">no-move</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-warning mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 5</h5>
            <p class="card-text">card 5</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-info mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 6</h5>
            <p class="card-text">card 6</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card bg-light mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 7</h5>
            <p class="card-text">card 7</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-dark mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 8</h5>
            <p class="card-text">card 8</p>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
  <!-- 부트스트랩 4.x를 사용한다. -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
  <script>
    $(function() {
      $(".column").sortable({
        // 드래그 앤 드롭 단위 css 선택자
        connectWith: ".column",
        // 움직이는 css 선택자
        handle: ".card-header",
        // 움직이지 못하는 css 선택자
        cancel: ".no-move",
        // 이동하려는 location에 추가 되는 클래스
        placeholder: "card-placeholder"
      });
      // 해당 클래스 하위의 텍스트 드래그를 막는다.
      $( ".column .card" ).disableSelection();
    });
  </script>
</body>
</html>

제가 이걸 만들어 놓고 보니깐 이 블로그의 부트스트랩 버전이 3.x라는 것을 이제 눈치챘습니다. ㅠ.ㅠ

그래서 3.x 버전으로 다시 만들었습니다.

<!DOCTYPE html>
<html>
<head>
  <title></title>
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <!-- 부트스트랩 3.x를 사용한다. -->
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<style>
  /* 리스트 css */
  .column{
    border: 1px solid #cecece;
    padding-top: 10px;
    padding-bottom: 10px;
    min-height: calc(70vh);
  }
  .container-fluid{
    margin-top: 20px;
  }
  /* 이동 타켓 */
  .card-placeholder {
    border: 1px dotted black;
    margin: 0 1em 1em 0;
    height: 50px;
    margin-left:auto;
    margin-right:auto;
    /* 노란색으로 표신되는 것이 주요 포인트 */
    background-color: yellow;
  }
  /* 마우스 포인터을 손가락으로 변경 */
  .card:not(.no-move) .card-header{
    cursor: pointer;
  }
  /* 부트스트랩 3.x에는 card 클래스 컴포낸트가 없으니 제가 만들었습니다. */
  .card{
    padding: 10px;
    border-radius: 5px;
    margin: 10px 0px;
  }
  .card-header{
    border-bottom: 1px solid;
    margin: 0px -10px;
    padding: 5px 10px;
    padding-top: 0px;
  }
</style>
<body>
  <div class="container-fluid">
    <div class="row">
      <!-- 세로 리스트 박스 -->
      <div class="col-sm-4 column">
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-primary mb-3 no-move">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 1</h5>
            <p class="card-text">no-move</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-info mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 2</h5>
            <p class="card-text">card 2</p>
          </div>
        </div>
      </div>
      <!-- 세로 리스트 박스 -->
      <div class="col-sm-4 column">
        <div class="card text-white bg-success mb-3 no-move">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 3</h5>
            <p class="card-text">no-move</p>
          </div>
        </div>
      </div>
      <!-- 세로 리스트 박스 -->
      <div class="col-sm-4 column">
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-danger mb-3 no-move">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 4</h5>
            <p class="card-text">no-move</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-warning mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 5</h5>
            <p class="card-text">card 5</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-info mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 6</h5>
            <p class="card-text">card 6</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card bg-danger mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 7</h5>
            <p class="card-text">card 7</p>
          </div>
        </div>
        <!-- 각 카드 리스트 박스 -->
        <div class="card text-white bg-primary mb-3">
          <div class="card-header">Header</div>
          <div class="card-body">
            <h5 class="card-title">card 8</h5>
            <p class="card-text">card 8</p>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
  <!-- 부트스트랩 3.x를 사용한다. -->
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  <script>
    $(function() {
      $(".column").sortable({
        // 드래그 앤 드롭 단위 css 선택자
        connectWith: ".column",
        // 움직이는 css 선택자
        handle: ".card-header",
        // 움직이지 못하는 css 선택자
        cancel: ".no-move",
        // 이동하려는 location에 추가 되는 클래스
        placeholder: "card-placeholder"
      });
      // 해당 클래스 하위의 텍스트 드래그를 막는다.
      $( ".column .card" ).disableSelection();
    });
  </script>
</body>
</html>

예제

Header
card 1

no-move

Header
card 2

card 2

Header
card 3

no-move

Header
card 4

no-move

Header
card 5

card 5

Header
card 6

card 6

Header
card 7

card 7

Header
card 8

card 8

위 예제를 확인해 보시면 됩니다.


jquery의 document로 가 보시면 예제가 거의 ul > li 로 되어있습니다. 디자인 템플릿을 사용하지 않으신다면 ul > li의 형식도 좋지만, 최근에는 많은 분들이 부트스트랩을 디자인 템플릿으로 기본으로 사용하고 있습니다.

그래서 저는 부트스트랩에 sortable를 사용할 수 있는 예제를 만들어 봤습니다.

요걸 잘 사용하신다면 아마 많은 웹의 위젯 프로그램에 응용으로 사용할 수 있습니다.


여기까지 Jquery의 Sortable(마우스 드래그 앤 드롭으로 리스트 정렬)에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.