728x90
반응형
728x90
반응형
728x90
반응형

에디터에서 흔히 많이 사용되는 input 영역에 2개 이상의 태그를 작성하기 위한 기능이 필요했다.

jQuery에서 사용할 수 있는 plugin을 찾아보니 Suggestags 라는 것이 있어 사용하기로 했다.

 

* plugin file download : https://github.com/amsify42/jquery.amsify.suggestags

* 환경 : jQuery v3.5.1, Bootstrap v4.5.3 사용, Suggestags 1.27.0 적용

 

1. plugin 적용

1
2
<link rel="stylesheet" href="/css/amsify.suggestags.css">
<script src="/js/jquery.amsify.suggestags.js"></script>
cs

 

2. 적용할 태그

1
<input type="text" class="form-control" id="tagsTxt">
cs

 

3. 내 소스에 적용

3-1. 기본 가이드

plugin  가이드 : https://openbase.com/js/suggestags/documentation

javascript 객체 상수 (constant) : https://webclub.tistory.com/527

기본적인 사용방법은 해당 가이드를 사용하면 된다.

3-2. 내가 필요했던 기능

1) javascript로 태그를 전부 다른 값으로 변경해야 한다.

2) javascript로 태그를 하나 추가하고 싶다.

3) 태그가 변경될 시 callback 이벤트를 사용하고 싶다.

3-3. 기존 소스의 문제점

다만 3-2의 내용들을 사용하기 위해서 refresh를 사용했는데

이 경우 기존에 선언시 설정했던 정보가 모두 날아가는 문제가 있었다.

 

3-4. 그래서 아래와 같은 함수를 만들어 적용했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// plugin 사용을 위한 값 세팅
definedValues();
// plugin 적용
usedSuggesTagsPlugin($('#tagsTxt'), 'init');
 
// 태그 전체 변경 변경시 
// tagsList : 'tag1,tag2' 형태의 스트링
usedSuggesTagsPlugin($('#tagsTxt'), 'setTags', {tags:tagsList});
 
// 태그 하나 추가 시
usedSuggesTagsPlugin($('#tagsTxt'), 'addTag', {tags:tag});
 
// javascript 객체 상수 (constant), 출처 : https://webclub.tistory.com/527
function definedValues(){
    constant.set('suggestagsSetting', {
        tagLimit : 10,                                      // 태그 최대 갯수 제한
        tags : '',                                          // 입력되는 태그 값
    });
}
 
/**
 * Suggestags의 사용을 위한 보조 함수
 * 출처 : https://openbase.com/js/suggestags/documentation
 * @param selector  : jquery형 selector
 * @param action    : 어떤 형태의 작업인지
 * => init : 사용을 위한 선언
 * => setTags : js로 태그 전체 변경시
 * => addTag : js로 태가 하나 추가시
 * => getClass : plugin에서 사용되는 클레스 값 전체를 구할때
 * @param value     : object형, action이 getClass인 경우 사용함
 * @returns
 */
function usedSuggesTagsPlugin(selector, action, value){
    if (isNull(selector))
        throw ': we need selector info for Suggestags plugin!';
    
    var objValue = !isNull(value) ?
            Object.assign(constant.get('suggestagsSetting'), value) 
            : constant.get('suggestagsSetting');
    
    // 선언시 세팅값 정의
    var objInit = {
            // 태그 반경시 callback 이벤트 설정
            afterAdd : function(e) {
                checkTagValuse();
            },
            afterRemove : function(e) {
                checkTagValuse();
            },
    };    
    if (!isNull(objValue) && !isNull(objValue.tagLimit) && Number(objValue.tagLimit) > 0) {
        Object.assign(objInit, {
            tagLimit: objValue.tagLimit
        });
    }
    
    // plugin 적용
    if (isNull(action) || action == 'init') {
        init();
        return;
    }
    
    if (!isNull(action) && (action == 'setTags' || action == 'addTag'
            && !isNull(objValue) && !isNull(objValue.tags)) {
        // refresh 사용시 tagLimit와 같은 기존 세팅 값이 초기화 되므로 재생성하도록 처리
        init();
        if (action == 'setTags') {
            var arrValue = objValue.tags.split(',');
            $.each(arrValue, function(i, e){
                amsifySuggestags.addTag(e.trim());
            });
            return;
        } else if (action == 'addTag') {
            amsifySuggestags.addTag(objValue.tags.trim());
            return;
        }
    } else if (!isNull(action) && action == 'setTags' 
        && !isNull(objValue) && isNull(objValue.tags)) {
        init();
        return;
    }
    
    /**
     * 사용예
     * 1. 아직 반영되지 않은 입력중인 태그 값을 구할때
     *  : $('input[class="'+usedSuggesTagsPlugin(selector, 'getClass').sTagsInput.substring(1)+'"]').val()
     */ 
    if(!isNull(action) && action == 'getClass') {
        amsifySuggestags = new AmsifySuggestags(selector);
        return amsifySuggestags.classes;
    }
    
    
    /* 내부함수 - 시작 */
    function init(){
        if (action != 'addTag') selector.val('');
        amsifySuggestags = new AmsifySuggestags(selector);
        amsifySuggestags.destroy();
        amsifySuggestags = new AmsifySuggestags(selector);
        amsifySuggestags._settings(objInit);
        amsifySuggestags._init();
    }
    
    // 태그 변경 시 이벤트 
    function checkTagValuse(){    
        // 입력된 태그 값을 비교하여 같거다 다른 경우 분기
    }
    /* 내부함수 - 끝 */
}
 
/**
 * param이 null, undefined, 공백 포함 빈 스트링인 경우 true, 값이 있는 경우 false
 * @param param
 */
function isNull(param){
    if(typeof param == "undefined" || param == null || param.length == 0
            || (typeof param == 'string' && (param == "" || param.trim().length == 0)))
        return true;
    else
        return false ;
}
cs

 

 

 

분명히 더 아름다운 방법이 있겠지만 우선 이렇게 마무리 했다.

(어후 삽질이야...)

 

728x90
반응형
728x90
반응형

input 태그에 작성값이 특정 조건에 맞지 않을때 기존 값을 다시 대입시키고 싶었다.

이에 적당한 코드가 있어서 기록해둠

1
2
3
4
5
6
7
8
9
10
11
$('input').on('focusin'function(){
    console.log("Saving value " + $(this).val());
    $(this).data('val', $(this).val());
});
 
$('input').on('change'function(){
    var prev = $(this).data('val');
    var current = $(this).val();
    console.log("Prev value " + prev);
    console.log("New value " + current);
});
cs

 

javascript의 focusin 이벤트와 change 이벤트, 커스텀 속성만 이해해 두면 아주 간단한 소스.

 

 

출처 : 

 

Input jQuery get old value before onchange and get value after on change

I have an input text in jQuery I want to know if it possible to get the value of that input text(type=number and type=text) before the onchange happens and also get the value of the same input inpu...

stackoverflow.com

 

728x90
반응형
728x90
반응형

spring에서 서버로 부터 받은 데이터를 object로 작업 후 서버로 보내고 싶었는데 불 필요한 데이터가 많았다.

게다가 해당 object 데이터는 배열까지 있는지라 하나하나 지우기에는 한계가 있었다.

그래서 이런 object에 필요없는 데이터가 많은 경우 한번에 제거하고 싶었다.

 

아래는 이런 문제의 예시가 될만한 object 데이터다.

내용을 살펴보면 값이 null인 경우도 많고, showFr, showTo 같은 값은 필요하지 않았다.

사실 여기서 crtDt, updDt, delDt와 같은 데이터가 가장 큰 문제였다.

이 데이터들은 javascript에서 보내줄 필요도 없고, spring 서버에서 알아서 관리할 데이터이다.

또한 spring에서는 Date 타입이기 때문에 이대로 보낸다면 에러가 날 뿐이다.

그래서 배열 내부까지 모두 제거가 필요했기 때문에 필요했다.

 

아래는 이러한 나의 요구에 맞게 만든 javascript 함수다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* Object 데이터 정리
* 호출 시 : objectCleanner(ObjectData, ['seq', 'showFr', 'showTo'], true)
 * @param objData : 클리닝 할 object 데이터
 * @param arrDeleteKey : 삭제할 key 배열
 * @param blKeyAdd : 키 배열에 기본 배열 추가 여부
 * @param objSub : 하위 object 데이터를 위한 변수
 * @returns
 */
function objectCleanner(objData, arrDeleteKey, blKeyAdd, objSub){
    if (!(objData instanceof Object)) return;
    if (!(arrDeleteKey instanceof Object)) return;
    
    // 기본 삭제 할 key 추가
    if (blKeyAdd) arrDeleteKey.push('delYn''crtDt''crtBy''updBy''updDt''delBy''delDt');
    
    var objCheck = typeof objSub == 'undefined' ? objData : objSub;
    
    var arrKey = Object.keys(objCheck);
    var arrVal = Object.values(objCheck);
    
    for (var i=0; i<arrKey.length; i++){
        // 해당되는 key이거나 value가 null 인 경우 삭제
        if (arrDeleteKey.indexOf(arrKey[i]) > -1 || arrVal[i] == null) {            
            delete objCheck[arrKey[i]];
        }
       // 재귀호출
        if (arrVal[i] instanceof Object
            cleaningObject(objData, arrDeleteKey, false, arrVal[i]);
    }
}
cs

 

호출시 

1
objectCleanner(detailDTO, ['showFr''showTo'], true);
cs

 

사용 후 object의 내용은 아래와 같이 정리된다.

 

 

 

728x90
반응형
728x90
반응형

* git URL : 클릭

 

1. 필요파일 : jquery.minicolors.css, jquery.minicolors.js, jquery.minicolors.min.js, jquery.minicolors.png

 

2. import

1
2
<link rel="stylesheet" href="/plugins/jquery-minicolors/jquery.minicolors.css">
<script src="/plugins/jquery-minicolors/jquery.minicolors.js"></script>
cs

 

3. minicolors를 위한 태그 추가

1
<input type="text" name="color1" class="form-control minicolors" data-control="hue" value="#ff6161" />
cs

(1) data-control 속성은 control 타입 사용시 어떤 스타일을 쓸 것인지 설정하는 것으로 hue, saturation, brightness, wheel 중 한가지 사용가능

(2) class에서 form-control은 bootstrap을 적용하고자 하는 경우 필요하므로 넣어주면 테마 적용에 용이

 

4. 세팅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$('.minicolors').each( function() {
    $(this).minicolors({
        control: $(this).attr('data-control'|| 'hue',
        defaultValue: $(this).attr('data-defaultValue'|| '',
        format: $(this).attr('data-format'|| 'hex',
        keywords: $(this).attr('data-keywords'|| '',
        inline: $(this).attr('data-inline'=== 'true',
        letterCase: $(this).attr('data-letterCase'|| 'lowercase',
        opacity: $(this).attr('data-opacity'),
        position: $(this).attr('data-position'|| 'bottom',
        swatches: $(this).attr('data-swatches') ? $(this).attr('data-swatches').split('|') : [],
                change: function(value, opacity) {
                    if!value ) return;
                    if( opacity ) value += ', ' + opacity;
                    iftypeof console === 'object' ) {
                        console.log(value);
                    }
                },
        theme: 'bootstrap'
    });
});
cs

(1) class의 minicolors에 해당되는 input 태그에 minicolors plugin을 적용

(2) 컬러 변경시 console log가 거슬리면 16번 라인 주석처리

(3) bootstrap을 사용하지 않는 경우 19번 라인에 theme : 'default' 로 변경

 

5. jquery 코드로 색상 변경

1
$(selecter).minicolors('value', hexValue);
cs

(1) hexValue 는 #ffffff 와 같은 형태

 

 

 

728x90
반응형
728x90
반응형

예를들어 라디오 버튼에서 변경시 이벤트를 적용하고 있다.

 

이때, 아래와 같이 동적으로 추가된 태그에서는 이미 적용했던 동일한 이벤트가 적용되지 않는다.

1
2
3
4
5
6
7
8
9
10
11
<!-- 기본html 작성된 tag -->
<input class="form-check-input" type="radio" id="qustList[0].pntY" name="qustList[0].pntYn" value="Y" checked>
<label class="form-check-label">Point Ues</label> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input class="form-check-input" type="radio" id="qustList[0].pntN" name="qustList[0].pntYn" value="N">
<label class="form-check-label">Point Not</label>
 
<!-- 동적으로 추가된 tag -->
<input class="form-check-input" type="radio" id="qustList[1].pntY" name="qustList[1].pntYn" value="Y" checked>
<label class="form-check-label">Point Ues</label> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input class="form-check-input" type="radio" id="qustList[1].pntN" name="qustList[1].pntYn" value="N">
<label class="form-check-label">Point Not</label>
cs

 

이와 같은 경우 아래와 같이 이벤트를 off 한 후 다시 on 하면 문제없이 원하는 이벤트를 적용할 수 있다.

1
2
3
4
$("input[name^='qustList['][name$='pntYn']").off("change");
$("input[name^='qustList['][name$='pntYn']").on("change"function(){
    // 적용할 코드
});
cs

 

 

* 관련글

[javascript] 동적 태그 추가 : https://deonggi.tistory.com/34

 

 

728x90
반응형
728x90
반응형

먼저 zTree 사용에 대한 기존 포스트가 있다.

해당 내용에 추가되는 내용이므로 zTree 사용방법을 모른다면 기존 포스트를 확인하기 바란다.

* [jquery] zTree plugin (tree view) : https://deonggi.tistory.com/110

 

# tree에 checkbox 추가를 위한 설정

1
2
3
4
5
6
7
8
9
10
11
12
var setting = {
    check : {
        enable: true,               // 체크박스 사용시
        chkDisabledInherit: true    // 체크박스 disabled 사용시
    },
    callback : {
        onClick: function(srcEvent, treeId, node, clickFlag) {
            // 클릭시 check toggle 처리
            zTreeObj.checkNode(node, nullfalse, $("#callbackTrigger").attr("checked"));                    
        },
    }
};
cs

 

개인적인 필요로 인해 2가지를 적용했다.

 

1. 코드로 check, uncheck 적용

내 경우 node 클릭 시 toggle로 checkbox 컨트롤이 필요해서 callback.onClick에 코드(위 소스의 9번 라인)가 추가 되었다.

 

* 참고 checkNode의 매개변수 설명

1
2
3
4
zTreeTools.checkNode = function (node, checked, checkTypeFlag, callbackFlag)
// checked : check여부, toggle 시 null
// checkTypeFlag : 하위 댑스가 있을때 하위 댑스도 check여부
// callbackFlag : $("#callbackTrigger").attr("checked") 
cs

 

2. disabled 적용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* zTree node ~ 하위node의 chkDisabled을 수정하기 위한 재귀함수
 * @param node
 * @param key
 * @returns
 */
function updateChkDisabled(node, key){
    
    if (typeof key != 'undefined' && key == 'reset') {        
        if (node.useYn == 'N') node.chkDisabled = true;    
        else delete node.chkDisabled; 
    } else {
        node.chkDisabled = true;        
    }
    
    zTreeObj.updateNode(node);
    $.each(node.children, function(index, subNode){
        updateChkDisabled(subNode, key);
    });
}
 
// chkDisabled all reset
$.each(zTreeObj.getNodes(), function(i, node){
    updateChkDisabled(node, 'reset');
});
 
/**
 * 타입에 따라 트리 disabled 처리
 * @param tp
 * @returns
 */
function changeChkDisabled(tp){    
    
    if(typeof tp != 'undefined') {
        if (tp != 'SUPER') {
            $.each(zTreeObj.getNodes(), function(i, node){
                if(node.tp == 'SUPER') updateChkDisabled(node, tp);
            });
        }      
    } 
}
cs

포인트는 node.chkDisabled = true로 처리하면 된다. 필요가 없다면 delete.

또한 해당 기능은 disabled 시 하위 node까지 동일 해야 한다.

1) 10번 라인은 내가 필요해 의해 넣은 내용으로 리셋시 useYn가 N이라면 disabled 처리

2) 23~25번 라인은 전체 리셋시 실행

3) 32~41번 라인은 tp가 'SUPER'가 아닌 경우, node.tp가 SUPER 이외의 것을 가진 node ~ 하위node 모두를 disabled 처리

4) 해당 소스는 23~25번을 먼저 호출하고, 상황에 따라(tp) 37번 라인 실행

 

다시 내 중심적으로 적은 내용이니, 다른 분들께서 사용하신다면 상황에 맞게 수정하여 사용하시면 되시겠다.

 

 

 

* 관련글

[jquery] zTree plugin (tree view)https://deonggi.tistory.com/110

[jQuery] zTree node children, updateNode() : https://deonggi.tistory.com/113

 

 

 

728x90
반응형
728x90
반응형

1. zTree 최하위 여부 체크 방법

1
2
3
4
5
6
7
8
9
// zTree를 초기화
var zTreeObj = $.fn.zTree.init($("#treeView"), setting);
 
var checkNodes = zTreeObj.getCheckedNodes(true);
$.each(checkNodes, function(index, node){
    if (typeof node.children == 'undefined') {
        // 최하위 일때 프로세스
    }
});
cs

 

 

2. zTree 하위까지 update 하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$.each(zTreeObj.getNodes(), function(index, node){
    updateChkDisabled(node);
});
 
function updateChkDisabled(node){
    // node 정보 변경 및 update
    node.chkDisabled = true;
    zTreeObj.updateNode(node);
 
    // 재귀함수로 하위 node 정보 변경 및 update
    $.each(node.children, function(index, sNode){
        updateChkDisabled(sNode);
    });
}
cs

 

 

 

* 관련글
[jquery] zTree plugin (tree view) : https://deonggi.tistory.com/110

[jquery, zTree] zTree의 checkbox 사용 : https://deonggi.tistory.com/118

 

 

728x90
반응형
728x90
반응형

뎁스가 있는 데이터를 관리할 화면이 필요했고, 인지하기 쉽게 윈도우 폴더 트리구조의 jquery 플러그인이 필요했다.

여러가지 적용해보고 쉽게 적용할 수 있는 플러그인을 찾아서 기록해 둔다.

 

# zTree 다운로드 링크, 데모와 document 링크

# 사용한 버전 :  v3.5.46

 

1. json 데이터로 간단한 트리 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var zNodes =[
    { 
      id: 1// unique ID
      pId: 0// parent ID
      name"Name"
      t: "Description"
      open: true // open this node on page load
    },
    { 
      id: 11
      pId: 1
      name"Node 1-1"
      t: "This is Node 1-1"
    },
    { 
        id: 12
        pId: 1
        name"Node 1-2"
        t: "This is Node 1-2"
    },
];
   
var setting = {
        data: {
          key: {
            title:"t"
          },
          simpleData: {
            enable: true
          }
        },
        // more settings here
    };
 
zTreeObj = $.fn.zTree.init($("#treeView"), setting, zNodes);
cs

 

2. ajax으로 받은 데이터로 트리 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
$(document).ready(function() {
    var setting = {
            data: {
                key: {
                    title:"t"
                },
                simpleData: {                    
                    enable: true
                }
            },
            async: {
                enable: true,
                type: "GET",
                url: AJAX_CALL_URL,
//                autoParam:["id", "name=n", "level=lv"],
//                otherParam:{"otherParam":"zTreeAsyncTest"},
               dataFilter: filter,
            },
            callback : {
                beforeClick : function(treeId, treeNode){                    
                },
                beforeAsync: function(treeId, treeNode){
                },
                onAsyncError: function(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown) {
                },
                onAsyncSuccess: function(event, treeId, treeNode, msg){
                },
                onNodeCreated: function(event, treeId, treeNode){                    
                },
                onClick: function(srcEvent, treeId, node, clickFlag){
                },
            }
    };
    zTreeObj = $.fn.zTree.init($("#treeView"), setting);
 
});
 
function filter(treeId, parentNode, childNodes) {
    if (!childNodes) return null;
    for (var i=0, l=childNodes.length; i<l; i++) {
        childNodes[i].name = childNodes[i].name.replace(/\.n/g, '.');
    }
    return childNodes;
}
cs

주의사항

1) 1의 zNodes와 같은 형태의 값을 리턴해 줄 것

2) AJAX_CALL_URL은 ajax url 값

3) dataFilter: filter 는 ajax 응답 후 필요한 데이터 처리가 있는 경우의 셈플

4) 전체 갱신이 필요한 경우 아래와 같이 사용

1
zTreeObj.reAsyncChildNodes(false'refresh'nullnull);
cs

5) 일부 갱신이 필요한 경우(트리최상위 node중 첫번째 node 아래로 전체 리플래시 됨) 

1
2
3
4
var nodes = zTreeObj.getNodes();
if (nodes.length>0) {
    zTreeObj.reAsyncChildNodes(nodes[0], "refresh"nullnull);
}
cs

6) 트리에서 선택한 항목의 데이터 얻기

1
var node = zTreeObj.getSelectedNodes();
cs

 

 

주석 처리된 부분은 데모에 있는 내용이었지만 아직 사용해 보지 않았기에 주석처리 했다.

 

 

* 관련글

[jQuery] zTree node children, updateNode() https://deonggi.tistory.com/113

[jquery, zTree] zTree의 checkbox 사용 : https://deonggi.tistory.com/118

 

 

 

728x90
반응형

+ Recent posts