본문 바로가기

WEB/내맘대로 코딩

드래그로 정렬가능한 컴포넌트

sortable 위젯 기능을 구현할 수 있는 가장 손쉬운 방법은 jquery-ui sortable 사용하는 것!

그런데 문제가 있다, 드래그만으로는 접근성에 위배된다. 장애인을 배려하지않는 ui/ux 구조!

손이 없거나 입으로 도구를 사용하는 장애인들에겐 드래그나 스와이프 행위가 쥐약이기 때문이다.

그래서 반드시 모바일에서는 터치할 수 있는 버튼이 존재해야 한다.

간혹, 없는 경우가 있는데 그건 접근성 통과후 제외시켰거나 접근성업체와의 물밑거래 후 권장사항으로 돌렸기 때문이다.

구글링을 하다보니, jquery-ui에 버튼 이동되는 컴포넌트를 발견했는데 angular로 구현되어 있었다.

참고 url : https://codepen.io/thgreasi/pen/Gqpiu

jquery만을 사용하여 똑같이 구현해보았으나, 역시 속도와 부드러움 정도는 js프레임워크를 따라갈 순 없었다.

html 영역이다.

<ul id="sortable">
        <li id="a">
            <div class="wrapper handle">
                <div class="line-wrapper">
                    <div class="line"></div>
                    <div class="line"></div>
                    <div class="line"></div>
                </div>
            </div>
            <span>Item A</span>
        </li>
        <li id="b">
            <div class="wrapper handle">
                <div class="line-wrapper">
                    <div class="line"></div>
                    <div class="line"></div>
                    <div class="line"></div>
                </div>
            </div>
            <span>Item B</span>
        </li>
        <li id="c">
            <div class="wrapper handle">
                <div class="line-wrapper">
                    <div class="line"></div>
                    <div class="line"></div>
                    <div class="line"></div>
                </div>
            </div>
            <span>Item C</span>
        </li>
        <li id="d">
            <div class="wrapper handle">
                <div class="line-wrapper">
                    <div class="line"></div>
                    <div class="line"></div>
                    <div class="line"></div>
                </div>
            </div>
            <span>Item D</span>
        </li>
    </ul>

css 영역이다.

*{margin:0;padding:0}
ul,li{list-style:none}
:root{font-size:62.5%}
body{font-size:16px}
#sortable li {position:relative;height:4.5rem;margin-top:-1px;border:1px solid #ddd;background:#fff;transition:all .3s ease-in-out;}
#sortable li.active{background:yellowgreen;}
#sortable li:after{content:'';display:inline-block;height:100%;vertical-align:middle}
#sortable li.ui-sortable-helper{background:wheat}
#sortable li.ui-sortable-placeholder{background:tomato;visibility:visible !important;}
#sortable li span{display:inline-block;padding:1rem;vertical-align:middle}
#sortable li .controls{position:absolute;right:1rem;top:50%;margin-top:-13px;z-index:1}
#sortable li button{position:relative;width:0;height:0;color:transparent;background:transparent;}
.up{
    top:-4px;
    border-top:10px solid transparent;
    border-bottom:10px solid red;
    border-right:10px solid transparent;
    border-left:10px solid  transparent;
}
.down{
    top:8px;
    border-top:10px solid blue;
    border-right:10px solid transparent;
    border-left:10px solid  transparent;
    border-bottom:10px solid transparent;
}
.wrapper{width:40px;height:36px;background:green;box-shadow:0 1px 5px rgba(0,0,0,.8);
position:absolute;top:4px;left:auto;right:8rem;cursor:pointer}
.line-wrapper{width:30px;height:15px;position:relative;top:7px;left:4px}
.line{background:#fff;margin-bottom:5px;width:30px;height:4px;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.5);position:relative;}

js 영역이다.

$(document).ready(function(){
    $("#sortable").sortable({
        handle: '.handle',
        create: function( event, ui){
            $(this).find('li').each(function(){
                $(this).append('<div class="controls"><button type="button" class="up">Up</button> <button type="button" class="down">Down</button></div>');
            });
        },
        start: function(  ){
        },
        stop: function( event, ui){
            var xxx = [];
            $(this).find('li').each(function(){
                xxx.push( $(this).attr('id') );
            });
            console.log(xxx);
        }
    });

    $(document).on('click','.up', function(){
        //console.log('up click');
        if( $(this).closest('li').prev().attr('id') != undefined ){
            var prevLi = $('#'+ $(this).closest('li').prev().attr('id') );
            prevLi.before( $('#'+ $(this).closest('li').attr('id') ).detach().addClass('active') );
            setTimeout(function(){
                prevLi.prev().removeClass('active');
            },500);
        }else{
            alert('더이상 위로 이동할 수 없습니다.');
            return;
        }
    });
    $(document).on('click','.down', function(){
        //console.log('down click');
        if( $(this).closest('li').next().attr('id') != undefined ){
            var NextLi = $('#'+ $(this).closest('li').next().attr('id') );
            NextLi.after( $('#'+ $(this).closest('li').attr('id') ).detach().addClass('active') );
            setTimeout(function(){
                NextLi.next().removeClass('active');
            },500);
        }else{
            alert('더이상 아래로 이동할 수 없습니다.');
            return;
        } 
    });
});

구현된 예시는 다음과 같다.

  •  
     
     
    Item A
  •  
     
     
    Item B
  •  
     
     
    Item C
  •  
     
     
    Item D

'WEB > 내맘대로 코딩' 카테고리의 다른 글

Bounce Effect  (0) 2021.08.11
최악의 슬라이드 플러그인 기능구현  (0) 2021.08.10
드래그로 정렬가능한 컴포넌트  (0) 2021.01.05
셀렉트박스 url 이동  (0) 2020.12.27
일반스크롤 vs 아이스크롤  (0) 2020.12.27
깜박임 효과  (0) 2020.12.15