// 스크롤 멈춤 감지
$.fn.scrollStopped = function (callback) {
    let _this = this, $this = $(_this);
    $this.scroll(function(event) {
        clearTimeout($this.data('scrollTimeout'));
        $this.data('scrollTimeout', setTimeout(callback.bind(_this), 250, event));
    });
};
addEventListener("scroll", e => {
    $(window).scrollStopped(function (ev) {
        // console.log("멈춤")
    });
})

 

let lastScrollY = 0;
addEventListener("scroll", e => {
                const scrollY = window.scrollY;
                // 스크롤 올렸을때, 내렸을때
                if (scrollY < lastScrollY) {
       
                } else {
 
                }
                // 현재의 스크롤 값을 저장
                lastScrollY = scrollY;
})

 

 

세션 스토리지를 리스트 유지에 많이 쓰이고는 하는데

세션스토리지에 리스트를 그리는용 데이터를 많이 던져두고는 하는데 여기서 최소한의 보안을 신경쓴 코드다

 

// 세션 스토리지 배열가져오기
function getArrSessionStorage(storageName) {
    if (JSON.parse(sessionStorage.getItem(storageName))) {
        let ArrData = JSON.parse(sessionStorage.getItem(storageName))
        ArrData = CryptoJS.AES.decrypt(ArrData, storageName);
        ArrData = JSON.parse(ArrData.toString(CryptoJS.enc.Utf8));
        return ArrData
    } else {
        return false;
    }
}
 
// 세션 스토리지 배열 저장
function setArrSessionStorage(storageName, ArrData) {
    ArrData = CryptoJS.AES.encrypt(JSON.stringify(ArrData), storageName).toString();
    sessionStorage.setItem(storageName, JSON.stringify(ArrData));
}
 

해당함수를 사용하기 위해서는 필수적으로 crypto-js가 설치 되어야한다

https://www.npmjs.com/package/crypto-js

 

crypto-js

JavaScript library of crypto standards.. Latest version: 4.1.1, last published: a year ago. Start using crypto-js in your project by running `npm i crypto-js`. There are 8744 other projects in the npm registry using crypto-js.

www.npmjs.com

 

 

셀렉 박스를 사용하다보면 
요구사항에 따라 기본 셀렉박스를 쓰면될거같은데
디자인의 통일성을 위해서 커스텀하게 사용하기를 원한다
이럴때 예전에는 justselect 라이브러리를 사용해서 쭉 써오다가
여기에서 더욱더 커스텀하게 사용하기를 원했다


그래서 라이브러리중 많은 부분을 뜯어 고쳤다

 

 

https://www.jqueryscript.net/form/dropdown-replacement-just-select.html

 

Bare-bones Select Dropdown Replacement - jQuery justselect

An extremely simple jQuery select replacement plugin that converts the native select dropdown into an easy to style HTML list while preserving the native select methods.

www.jqueryscript.net

다운받아서 min.js 파일을 열어보면 이런 코드로 짜여있다. 

$(document).ready(function () {
    $(".justselect").each(function () {
        $(this).wrap('<div class="justselect-wrapper">');
        var e = document.createElement("ul");
        e.className = "justselect-list";
        var t = document.createElement("div");
        t.className = "justselect-title"; var s = $(this).parent(),
            l = $(this).find($("option"));
        for (s.append(t, e), i = 0; i < l.length; i++){
            var c = document.createElement("li");
            e.append(c), justselectLI_option = s.find($(".justselect-list li")),
                justselectLI_option.eq(i).text(l.eq(i).text()),
                l.eq(i).attr("selected") && (justselectLI_option.eq(i).addClass("selected"),
                    s.find($(".justselect-title")).text(justselectLI_option.eq(i).text())),
                justselectLI_option.click(function () {
                    $(this).addClass("selected").siblings().removeAttr("class");
                    var e = $(this).index();
                    s.find($(".justselect-list")).fadeOut(),
                        $(".justselect-body-overlay").remove(),
                        l.eq(e).attr("selected", !0).siblings().removeAttr("selected"),
                        s.find($(".justselect-title")).text($(this).text())
            })
        } s.find($(".justselect-title")).click(function () {
            s.find($(".justselect-list")).fadeToggle();
            var e = document.createElement("div");
            e.className = "justselect-body-overlay",
                $("body").prepend(e),
                $(".justselect-body-overlay").click(function () {
                    s.find($(".justselect-list")).fadeToggle(),
                    $(".justselect-body-overlay").remove()
                })
        })
    })
});

개인적으로 별로 안좋아하는
 createElement 를 남발하면서 짜여있는데
성능 측면으로는 효율적인지 아닌지는 잘모르겠지만
가독성 측에서는 읽기가 너무 불편해서 우선 이부분부터 수정했다.

그리고 커스텀하게 쓰기 위해서는 클래스명을 내맘대로 지정할 수 있어야 한다.
그리고 기본으로 적용되어서 커스텀하게 사용하지 못하는 부분은
입맛대로 원하는 대로 min.css 를 수정하면 된다.


수정한 결과물을 공유하면 이렇게 수정했다.

makeClassName 매개변수로 셀렉박스 별로 모양을 여러개 만들어서 돌려서 사용할 수 있도록 의도했다.

여기서 조금더 커스텀 하고싶다 한다면 매개변수를 추가하고 클래스를 직접 지정하면 된다.

tagetSelectId 매개변수는 셀렉박스 고유 아이디를 작성해서 하나의 페이지에 다양한 셀렉박스를 만들수 있다
 

function makeJustSelect(makeClassName, tagetSelectId) {
    $(`#${tagetSelectId}`).each(function () {
        // 가장 큰 요소 생성
        $(this).wrap(`<div class="justselect-wrapper wrapper-${makeClassName}">`);
        let s = $(this).parent();
        l = $(this).find($("option"));

        // 셀렉박스 제목이 될 부분 지정
        let t = ``;
        t = `<div class="justselect-title title-${makeClassName}"></div>`
        $(`.wrapper-${makeClassName}`).append(t);

        // 셀렉박스 ul 태그 생성
        let e = ``;
        e = `<ul class="justselect-list list-${makeClassName}"></ul>`
        $(`.wrapper-${makeClassName}`).append(e);

        // 셀렉박스 li 태그 생성
        for (i = 0; i < l.length; i++){
            let c = ``;
            if (l.eq(i).attr("selected")) {
                c = `<li class="justselect-cell cell-${makeClassName} selected">${l[i].text}</li>`;
                $(`.title-${makeClassName}`).text(l.eq(i).text()); // 제목 텍스트 지정
            } else {
                c = `<li class="justselect-cell cell-${makeClassName}">${l[i].text}</li>`;
            }
            $(`.list-${makeClassName}`).append(c);
        }

        // 셀렉박스 오픈시
        s.find($(`.title-${makeClassName}`)).click(function () {

            let touchOverlay = $("body").find($(".justselect-body-overlay")).length; // z-index 꼬임방지

            if (touchOverlay === 0) {
                s.find($(`.list-${makeClassName}`)).fadeToggle();
                let bigBox = ``;
                bigBox = `<div class="justselect-body-overlay"></div>`
                $("body").prepend(bigBox);
                $(this).addClass("active"); // 클릭시 구분 클래스명 추가
            } else {
                $(this).removeClass("active");
                s.find($(".justselect-list")).fadeToggle();
                $(".justselect-body-overlay").remove();
            }

            $(".justselect-body-overlay").click(function () {
                $(`.title-${makeClassName}`).removeClass("active");
                s.find($(".justselect-list")).fadeToggle();
                $(".justselect-body-overlay").remove();
            })

        })

        // 항목클릭시
        s.find($(`.cell-${makeClassName}`)).click(function () {
            $(`.title-${makeClassName}`).removeClass("active");
            $(this).addClass("selected").siblings().removeClass("selected");
            var e = $(this).index();
            s.find($(`.list-${makeClassName}`)).fadeOut();
            $(".justselect-body-overlay").remove();
            l.eq(e).attr("selected", !0).siblings().removeAttr("selected");
            s.find($(`.title-${makeClassName}`)).text($(this).text());
        })
    })
}

HTML

selected 는 초기 셀렉박스 제목지정을 위해서 필수로 입력해야한다.

 
 
    <select class="justselect" name="폼전송이름" id= "셀렉트아이디" >
        <option value="값1" selected>값~!</option>
        <option value="값2">값~@</option>
        <option value="값3">값~#</option>
        <option value="값4">값~$</option>
    </select>
 

 

<script type="text/javascript" src="앞주소/js/justselect.min.js"></script>
 
makeJustSelect 함수의 매개변수는 구분할 임의의 문자로 지정해서 css를 정하는데 활용하면 된다.
 
<script>
makeJustSelect("클래스구분명",  "셀렉트아이디");
</script>

 

 

상단의 코드로는 한페이지에 하나의 셀렉박스만 적용이 되어서
셀렉박스를 여러개를 생성해서 사용하기 위해서 고유 아이디로 값찾아서 조절하게끔 조금 수정했다
범용적인 것을 원한다면 아래의 코드를 사용하자!

 



function makeJustSelect(makeClassName, tagetSelectId) {

    let tagetObject = $(`#${tagetSelectId}`)

    /* 가장 큰 요소 생성 */
    tagetObject.wrap(`<div class="justselect-wrapper wrapper-${makeClassName}" id="wrapper_${tagetSelectId}">`);
    let tagetObject_parent = tagetObject.parent();
    let tagetObject_option = tagetObject.find($("option"));

    /* 셀렉박스 제목이 될 부분 지정 */
    let makeTitle = ``;
    makeTitle = `<div class="justselect-title title-${makeClassName}" id="title_${tagetSelectId}"></div>`
    $(`#wrapper_${tagetSelectId}`).append(makeTitle);

    /* 셀렉박스 ul 태그 생성 */
    let makeList = ``;
    makeList = `<ul class="justselect-list list-${makeClassName}" id="list_${tagetSelectId}"></ul>`
    $(`#wrapper_${tagetSelectId}`).append(makeList);

    /* 셀렉박스 li 태그 생성 */
    for (i = 0; i < tagetObject_option.length; i++){
        let makeCell = ``;
        if (tagetObject_option.eq(i).attr("selected")) {
            makeCell = `<li class="justselect-cell cell-${makeClassName} cell_${tagetSelectId} selected">${tagetObject_option[i].text}</li>`;
            $(`#title_${tagetSelectId}`).text(tagetObject_option.eq(i).text()); /* 제목 텍스트 지정 */
        } else {
            makeCell = `<li class="justselect-cell cell-${makeClassName} cell_${tagetSelectId}">${tagetObject_option[i].text}</li>`;
        }
        $(`#list_${tagetSelectId}`).append(makeCell);
    }

    /* 셀렉박스 오픈시 */
    tagetObject_parent.find($(`#title_${tagetSelectId}`)).click(function () {
        let touchOverlay = $("body").find($(".justselect-body-overlay")).length; /* z-index 꼬임방지 */
        if (touchOverlay === 0) {
            tagetObject_parent.find($(`#list_${tagetSelectId}`)).fadeToggle();
            let bigBox = ``;
            bigBox = `<div class="justselect-body-overlay"></div>`
            $("body").prepend(bigBox);
            $(this).addClass("active"); /* 클릭시 구분 클래스명 추가 */
        } else {
            $(this).removeClass("active");
            tagetObject_parent.find($(".justselect-list")).fadeToggle();
            $(".justselect-body-overlay").remove();
        }
        $(".justselect-body-overlay").click(function () {
            $(`#title_${tagetSelectId}`).removeClass("active");
            tagetObject_parent.find($(".justselect-list")).fadeToggle();
            $(".justselect-body-overlay").remove();
        })
    })

    /* 항목클릭시 */
    tagetObject_parent.find($(`.cell_${tagetSelectId}`)).click(function () {
        $(".justselect-body-overlay").remove();
        var cellIdx = $(this).index();
        tagetObject_option.eq(cellIdx).attr("selected", !0).siblings().removeAttr("selected");
        $(this).addClass("selected").siblings().removeClass("selected");
        $(`#title_${tagetSelectId}`).removeClass("active");
        tagetObject_parent.find($(`#title_${tagetSelectId}`)).text($(this).text());
        tagetObject_parent.find($(`#list_${tagetSelectId}`)).fadeOut();
    })
}
makeJustSelect("스타일클래스명", "구분고유아이디");
$('body').on('click', `#list_만들때고유아이디`, function (e) {
 
)}

 

css

.justselect-body-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:2}
.justselect{display:none}
.justselect-wrapper{position:relative; width:auto}
.justselect-title{ cursor:pointer; background-repeat:no-repeat;}
.justselect-list{position:absolute; width:100%;list-style:none;padding:0;
    border:1px solid #ebebeb;-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;border-radius:5px;
    -webkit-box-shdow:0 0 10px rgba(0,0,0,.05);-moz-box-shadow:0 0 10px rgba(0,0,0,.05);box-shadow:0 0 10px rgba(0,0,0,.05);
    display:none; z-index:3; overflow:hidden; margin:0;}
.justselect-list li {line-height:40px;cursor:pointer; padding:0 16px; background:white}
/* .justselect-list li.selected {background:#ebebeb} */
.justselect-list .active {display:block}

 

 

load 함수를 모달 불러오는 곳에서 사용해서

모달정보를 불러오기전에 컨트롤러를 거쳐서 모달을 띄울지말지 정해야 하는데

 

컨트롤러에 애초에 뿌릴때 data- 태그에 값을 넣어서 구분할 수 있지만

모달에 대한 예외처리가 부족한거 같아서 조금 더 파보았다

 

        // 모달 불러오기 예외 처리
        $('선택자').load(url, function(response) {
            if (response) {
                $("#모달부분").css("display", "block");
            } else {
                swalAlert("예외 알림창")
            }
        });

 

이렇게 사용했지만 function 에서

불러온 데이터, 요청 결과 상태 (200, 404 등), xmlhttpRequest 객체

이렇게 3가지를 받아올 수 있지만 의도한대로 풀기위해서는 첫번째만으로 충분했다

이전글에서 추가 기능은 동일하지만 삭제 기능은 ajax를 사용해서 삭제하고 html 해당 부분을 지워주는 처리를 했다.

그리고 지우는 옵션이 마지막 옵션일경우 옵션 박스를 지워주는 코드도 추가했다.

 
        if (result['contentsData'] == true ) { // 통신 성공했을떄
 
            let div = document.getElementById(result["resultClass"]); // 지울대상 가져오기 

            div.parentNode.removeChild(div); // 해당 대상 지우기

            if (result["resultParent"] != "N") {  // 옵션박스를 지우는건지 아닌지 체크  
                let parentDiv = document.getElementById("옵션담는박스+번호");

                if (parentDiv.childElementCount == 0 ) {
                    parentDiv = document.getElementById("옵션박스+번호");
                    parentDiv.parentNode.removeChild(parentDiv);
                }
            }


        } else {
            alert("삭제 실패했습니다.");
        }

 

선택 옵션의 데이터를 기준으로 데이터를 불러온다. 이렇게 부르면 이전글을 참고하면 카메라의 데이터가 각각의 0123의 데이터에 담긴채 하나의 배열로 들고온다.

저장된 옵션데이터를 조회해서 순차적으로 넣어주기만 하면된다고 생각했다 이미 앞전에서 데이터를 순차적으로 넣는게 가능했기 때문이다. 하지만 순차적으로 입력, 수정이 된다해도 삭제만하고 수정동작을 통해 정렬을 다시 해주지 않았다면 여기서 로직이 더 추가된다.

            let isOption = -1; // 옵션 구분
            let optionNum = -1; // 옵션 생성
                // 옵션 html추가
                if (isOption !== parseInt(data["저장한_순서_조회"])) {
                    optionAdd();
                    isOption = parseInt(data["저장한_순서_조회"])
                    optionNum++;
                }

isOption 변수는 다음 옵션박스로 넘어갔는지 체크한다 넘어갔으면 옵션박스를 그리고 넘어간 번호를 변수에 저장하고

생성할 옵션박스의 순서를 optionNum 에 저장한다. 

 

 

이번에는 상품관리 페이지를 구현하던중 코드를 어떻게 구성할지 고민을 많이 했다

 

 

 

등록할때는 아래와 같은 형식으로 작성하면 된다

여기서 핵심 로직구성은 이렇다

  0

  1

  2

  4 (3번이 생성되었다 삭제 되었다 다시 만든경우)

2 (상품박스를 중간에 삭제한 경우)

  0

3

  1

  3

 

 

이런식으로 셀렉트 박스가 구성되었다고 한다면 0번째 상품에 0 1 2 4 의 선택 할 수 있는 옵션이있고

예를들어 0번째 상품(카메라) 0 1 2 4 의 옵션 (각 다른 카메라 모델) 이런식으로 구성할 수 있다

 

여기서 데이터를 저장할때 일관성있게 저장하고 싶을때 어떻게 해야할까

이미 셀렉트 박스의 일관성은 무너졌고 셀렉트박스 안에 소속된 옵션의 순서도 순차적이다 라는 조건이 무너졌다

 

삭제가 일어날때마다 변수의 카운트를 줄여서 해결한다 -> 이방법은 사용할 수 없다

예를들어 01234 까지 생성하고 4번을 삭제하고 다시 생성해서 사용하면 카운트를 줄이고 늘리는 방식으로 해결이 가능하다. 하지만 3번을 지웠다면 예외처리를 한다하더라도 순차적이지 않다 

 

그래서 이렇게 접근했다 0 2 3 번이 생성되었고 여기 번호에 접근해야한다는것을 알리는 정보를 담은 input name="arrVal[]" 의 정보와 0번째에 접근해서 값을 받으면 0 1 2 4 번이 데이터를 보냈다는 정보를 앞과 같이 보냈다

이렇게 하면 foreach 문을 돌며 데이터의 순번과 접근해야하는 데이터 정보까지 얻을 수 있다

 

 

 

 

 

 

<div class="" name="saleOptionBox" id="saleOptionBox"  style="background-color: lightsteelblue; height: auto; padding: 20px; margin: 50px 0; border-radius: 20px;">
</div>
<div class="" style="display: flex;">
	<button type="button" class="btn btn-default optionAdd" id="optionAdd" >큰박스 추가</button>
</div>

 

<script>
		optionAdd();
        optionValAdd("saleOptionBox"+(contOp-1), contOp-1)
        
        $('body').on('click', '.optionAdd', function(e) {
            optionAdd();
            optionValAdd("saleOptionBox"+(contOp-1), contOp-1)
        });

<!-- 큰박스 추가 함수 -->
    let contOp = 0;
    function optionAdd() {
		let htmlTag = "";
        htmlTag += `<button type="button" class="btn btn-default" onclick='optionValAdd("saleOptionBox${contOp}", ${contOp})'>작은박스 추가</button>`;
   		contOp++;
        $('#saleOptionBox').append(htmlTag);
    }

    let contOpVal = 0;
    function optionValAdd(addTargetId, optionI) {
    	let htmlTag = "";
		contOpVal++;
        $(`#${addTargetId}`).append(htmlTag);
    }
    
    
</script>
 

 

+ Recent posts