login register Sysop! about ME  

2018년 07월 05일 16시 35분 00초,     조회수 : 475
  제목 : css grid 추가/ 삭제/ 합치기/ 나누기 기능 좀 개발해 주실 수 있을까요?
SEQ : 37009 글쓴이 : autodoc

작성 포맷 : TEXT 모드, 자동 줄바꿈 사용

저도 코딩은 여러가지 열심히 공부하고 있고 언급한 기능을 table로 구현하는 javascript 소스는 어찌어찌 구했는데 계속 
들여다보면서 공부해 보지만 제 실력으로는 불가능하다는 결론… ㅠㅠ

그래서 첨부한 자료의 table을 삽입/삭제/합치기/나누기 하는 javascript를 CSS에서 지원되는 grid를 삽입/삭제/합치
기/나누기 하는 javascript로 변형하는 요청을 드리고자 합니다.

그냥 단순하게 바꾸는게 아니라서 쉽지는 않은듯도… 
아래 코딩 전부 무시하고 제가 원하는 기능으로 다른 javascript 등 전용툴로 구현해주셔도 되는데 어떤게 더 빠를지 모르겠습
니다.

수고료는 너무 적은듯하여 송구하지만 이십만 정도 생각하는데…
보시고 의향있으신 분은 연락주시면 감사… 공일공팔구삼공팔이삼칠

파일이 생각보다 길어서 보시는데 불편할듯도 한데 첨부 기능이 없어서 부득이....

===================개발하고자 하는 기본 html page: index_grid.html================
본문 내용 중에 상세 요건이 있습니다.

<!DOCTYPE html>
<html>
<head>
  <title></title>

  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

  <script type="text/javascript" src="redips-table-min.js"></script>
  <script type="text/javascript" src="script-table.js"></script>

  <style>
        body {
            margin: 0px;
        }

        #grid-container {
            display: grid;
            width:1000px;
            grid-template-columns: auto;
            grid-gap: 5px;
            background-color: #2196F3;
            padding: 5px;
        }

        .container_c {
            background-color: rgba(255, 255, 255, 0.8);
            text-align: center;
            padding: 5px;
            font-size: 15px;
            height:auto;
            min-height:200px;
        }

        /* container */
        #myContainer {
            width:1000px;
            margin: 0px auto;
            border: 2px solid LightBlue;
            display: table;
            text-align:center;
        }

        /* button styles */
        .button {
            background-color: #4CAF50; /* Green */
            border: none;
            color: white;
            text-align: center;
            text-decoration: none;
            margin: 4px 2px;
            cursor: pointer;
            padding: 7px 40px;
            border-radius: 4px;
        }

        .menu {
            display:inline-block;
        }
  </style>
  </head>

  <script>
    //여기에 필요한 javascript code를 넣어주세요.
  </script>

<body>
    <h3>Grid Cell Transformer</h3>

    <div>
        1. 아래 기능을 구현하기 위하여 redips-table-min.js와 script-table.js를 변경하거나 이 파일의 script 부분을 변경하
세요<br>
        2. 각 class나 id의 이름은 변경하지 않음<br>
        3. container1, container2, container3,...., containern의 형태로 id가 부여되어야 함<br>
        4. 화면에서 각각의 container 번호로 각각의 container에 표시되어야 함 (containern은 n으로 표기됨)<br>
        5. 열과 행의 삽입 위치는 이용자가 선택할 수 있으며 선택하지 않는 경우 마지막 행이나 열 뒤에 추가됨<br>
        6. 삽입 위치 지정 select 메뉴에는 삽입된 열과 행의 수만큼의 행과 열의 숫자가 나타나야 함<br>
        7. 삽입된 행의 화면 너비는 전부 동일하여야 함 (예를 들어 3개 column인 경우 각 container 너비가 33.33%가 됨)
<br>
        8. 최초 또는 삽입된 열의 화면 높이는 자동으로 설정되어야 하나 최소 200px 높이가 되어야 함<br>
        9. grid에서 열과 행을 합친 경우 style sheet에서 각 container별로 grid-area가 javascript에 의해 자동으로 삽입되
어야 함<br>
        (예를 들어 grid-area: 2/2/5/4가 style sheet에 삽입된 코딩은 2열2행부터 4열3행까지가 1개의 cell로 합쳐진다는 
의미임)<br>
        10. 합쳐진 행이나 열의 container 번호는 합쳐지지 전의 각 cell의 번호 중 가장 작은 container 번호로 표기됨<br>
        11. 1개 cell 상태(default 화면)에서 삭제 메뉴 선택 시 "2개 이상의 행이 필요합니다"/ "2개 이상의 열이 필요합니
다"라는 경고창 띄위기<br>
        12. 현재 가용한 table 변형 javascript 소스는 https://www.redips.net/javascript/table-td-merge-split/에 있음
<br>  
    </div>

    <div>&nbsp;</div>
    <!-- container -->
    <div id="myContainer">
        <!-- toolbox -->
        <div class="menu">
            <input type="button" class="button" value="Merge" onclick="redips.merge()" title="합칠 여러개 셀 선
택"/>
            <input type="button" class="button" value="Split H" onclick="redips.split('h')" title="수평 분할 셀 선
택"/>
            <input type="button" class="button" value="Split V" onclick="redips.split('v')" title="수직 분할 셀 선
택"/>
            <input type="button" class="button" value="Row -" onclick="redips.row('delete')" title="1개 행 삭제"/>
            <input type="button" class="button" value="Col -" onclick="redips.column('delete')" title="1개 열 삭
제"/>
        </div>

        <div>
            <input type="button" class="button" value="Row +" onclick="redips.row('insert')" title="1개 행 삽입"/>
            삽입 위치 지정
                <select>
                    <option "selected" value="마지막 행"> 마지막 행</option>
                    <option value="1"> 1</option>
                    <option value="2"> 2</option>
                    <option value="3"> 3</option>
                </select>

                <select>
                    <option "selected" value="뒤"> 뒤</option>
                    <option value="앞"> 앞</option>
                </select>
        </div>

        <div>
            <input type="button" class="button" value="Col +" onclick="redips.column('insert')" title="1개 열 삽
입"/>
            삽입 위치 지정
                <select>
                    <option "selected" value="마지막 열"> 마지막 열</option>
                    <option value="1"> 1</option>
                    <option value="2"> 2</option>
                    <option value="3"> 3</option>
                </select>

                <select>
                    <option "selected" value="뒤"> 뒤</option>
                    <option value="앞"> 앞</option>
                </select>
        </div>

        <div>&nbsp;</div>

        <div id="grid-container">
            <div class="container_c" id="container1">1</div>
        </div>

        <div>
            현재 행의 개수: ?<br>
            현재 열의 개수: ?
        </div>
    </div>

</body>
</html>

===========기존 table 기준 cell 추가/삭제/ 합치기/ 나누기 페이지: index_table.html============
<!DOCTYPE html>
<html>
<head>
	   <title></title>

	   <meta charset="utf-8" />
	   <meta name="viewport" content="width=device-width, initial-scale=1">

	   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
	   <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

    <script type="text/javascript" src="redips-table-min.js"></script>
    <script type="text/javascript" src="script-table.js"></script>

    <style>
        body {
            margin: 0px;
        }

        /* container */
        #myContainer {
            width:1000px;
            margin: 0px auto;
            /*border: 2px solid LightBlue;*/
            display: table;
            text-align:center;
        }

        /* both tables */
        div#myContainer table {
            width:100%;
            min-height:300px;
            border-collapse: collapse;
            /* border-collapse: separate; */
            border-spacing: 1px;
        }

        /* main table */
        #mainTable {
            color: #777;
            background-color: #eee;
            margin: 7px;	   
        }

        /* table cells */
        div#myContainer td {
            height:100px;
            min-height:50px;
            border: 1px solid navy;
            text-align: center;
            padding: 0;
        }

        /* button styles */
        .button {
            background-color: #4CAF50; /* Green */
            border: none;
            color: white;
            text-align: center;
            text-decoration: none;
            margin: 4px 2px;
            cursor: pointer;
            padding: 7px 40px;
            border-radius: 4px;
        }

        .menu {
            display:inline-block;
        }
    </style>
</head>

<body>
    <h3>Table Cell Transformer</h3>
    <!-- container -->
    <div id="myContainer">
        <!-- toolbox -->
        <div class="menu">
            <input type="button" class="button" value="Merge" onclick="redips.merge()" title="합칠 여러개 셀 선
택"/>
            <input type="button" class="button" value="Split H" onclick="redips.split('h')" title="수평 분할 셀 선
택"/>
            <input type="button" class="button" value="Split V" onclick="redips.split('v')" title="수직 분할 셀 선
택"/>
            <input type="button" class="button" value="Row +" onclick="redips.row('insert')" title="1개 행 삽입"/>
            <input type="button" class="button" value="Row -" onclick="redips.row('delete')" title="1개 행 삭제"/>
            <input type="button" class="button" value="Col +" onclick="redips.column('insert')" title="1개 열 삽
입"/>
            <input type="button" class="button" value="Col -" onclick="redips.column('delete')" title="1개 열 삭
제"/>
        </div>
        
        <!-- main table -->
        <table id="mainTable">
            <tr>
                <td></td>
            </tr>
        </table>
    </div>
</body>
</html>

============== 관련 javascript 파일: script-table.js============
/*jslint white: true, browser: true, undef: true, nomen: true, eqeqeq: true, plusplus: false, bitwise: true, 
regexp: true, strict: true, newcap: true, immed: true, maxerr: 14 */
/*global window: false, REDIPS: true */

/* enable strict mode */
"use strict";

// create redips container
var redips = {};


// REDIPS.table initialization
redips.init = function () {
	   // define reference to the REDIPS.table object
	   var rt = REDIPS.table;
	   // activate onmousedown event listener on cells within table with id="mainTable"
	   rt.onmousedown('mainTable', true);
	   // show cellIndex (it is nice for debugging)
	   rt.cell_index(true);
	   // define background color for marked cell
	   rt.color.cell = '#9BB3DA';
};


// function merges table cells
redips.merge = function () {
	   // first merge cells horizontally and leave cells marked
	   REDIPS.table.merge('h', false);
	   // and then merge cells vertically and clear cells (second parameter is true by default)
	   REDIPS.table.merge('v');
};


// function splits table cells if colspan/rowspan is greater then 1
// mode is 'h' or 'v' (cells should be marked before)
redips.split = function (mode) {
	   REDIPS.table.split(mode);
};


// insert/delete table row
redips.row = function (type) {
	   REDIPS.table.row('mainTable', type);
};


// insert/delete table column
redips.column = function (type) {
	   REDIPS.table.column('mainTable', type);
};


// add onload event listener
if (window.addEventListener) {
	   window.addEventListener('load', redips.init, false);
}
else if (window.attachEvent) {
	   window.attachEvent('onload', redips.init);
}

============== 관련 javascript 파일2: redips-table-min.js=====================
/*
Copyright (c)  2008-2012, www.redips.net  All rights reserved.
Code licensed under the BSD License: http://www.redips.net/license/
http://www.redips.net/javascript/table-td-merge-split/
Version 1.1.0
May 15, 2012.
*/
"use strict";

var REDIPS=REDIPS||{};

REDIPS.table=(function(){
    var 
onmousedown,handler_onmousedown,merge,merge_cells,max_cols,split,get_table,mark,cell_init,row,column,c
ell_list,relocate,remove_selection,cell_index,cell_ignore,tables=[],td_event,show_index,color=
{cell:false,row:false,column:false
    },mark_nonempty=true;

    onmousedown=function(el,flag,type){
        var td,i,t,get_tables;
        get_tables=function(el){
            var arr=[],nodes,i;
            nodes=el.getElementsByTagName('table');
            for(i=0;i<nodes.length;i++){
                arr.push(nodes[i]);
            }
            return arr;
        };
    
        td_event=flag;
    
        if(typeof(el)==='string'){
            if(type==='classname'){
                tables=get_tables(document);
                for(i=0;i<tables.length;i++){
                    if(tables[i].className.indexOf(el)===-1){
                        tables.splice(i,1);
                        i--;
                    }
                }
            }else{
                el=document.getElementById(el);
            }
        }

        if(el&&typeof(el)==='object'){
            if(el.nodeName==='TABLE'){
                tables[0]=el;
            }else{
                tables=get_tables(el);
            }
        }

        for(t=0;t<tables.length;t++){
            td=tables[t].getElementsByTagName('td');
            for(i=0;i<td.length;i++){
                cell_init(td[i]);
            }
        }
        cell_index();
    };

    cell_init=function(c){
        if(c.className.indexOf('ignore')>-1){
            return;
        }

        if(td_event===true){
            REDIPS.event.add(c,'mousedown',handler_onmousedown);
        } else{
            REDIPS.event.remove(c,'mousedown',handler_onmousedown);
        }
    };

    cell_ignore=function(c){
        if(typeof(c)==='string'){
            c=document.getElementById(c);
        }

        REDIPS.event.remove(c,'mousedown',handler_onmousedown);
    };

    handler_onmousedown=function(e){
        var evt=e||window.event,td=evt.target||evt.srcElement,mouseButton,empty;
        empty=(/^\s*$/.test(td.innerHTML))?true:false;

        if(REDIPS.table.mark_nonempty===false&&empty===false){
            return;
        }

        if(evt.which){
            mouseButton=evt.which;
        }else{
            mouseButton=evt.button;
        }

        if(mouseButton===1){
            td.redips=td.redips||{};

            if(td.redips.selected===true){
                mark(false,td);
            }else{
                mark(true,td);
            }
        }
    };

    merge=function(mode,clear,table){
        var tbl,tr,c,rc1,rc2,marked,span,id,cl,t,i,j,first={index:-1,span:-1};

        remove_selection();
        tbl=(table===undefined)?tables:get_table(table);
        for(t=0;t<tbl.length;t++){
            cl=cell_list(tbl[t]);
            tr=tbl[t].rows;
            rc1=(mode==='v')?max_cols(tbl[t]):tr.length;
            rc2=(mode==='v')?tr.length:max_cols(tbl[t]);
            for(i=0;i<rc1;i++){
                first.index=first.span=-1;
                for(j=0;j<=rc2;j++){
                    id=(mode==='v')?(j+'-'+i):(i+'-'+j);
                    if(cl[id]){
                        c=cl[id];
                        c.redips=c.redips||{};
                        marked=c?c.redips.selected:false;
                        span=(mode==='v')?c.colSpan:c.rowSpan;
                    }else{
                        marked=false;
                    }

                    if(marked===true&&first.index===-1){
                        first.index=j;
                        first.span=span;
                    }else if((marked!==true&&first.index>-1)||(first.span>-1&&first.span!==span)){
                        merge_cells(cl,i,first.index,j,mode,clear);
                        first.index=first.span=-1;
                        if(marked===true){
                            if(clear===true||clear===undefined){
                                mark(false,c);
                            }
                            marked=false;
                        }
                    }

                    if(cl[id]){
                        j+=(mode==='v')?c.rowSpan-1:c.colSpan-1;
                    }
                }

                if(marked===true){
                    merge_cells(cl,i,first.index,j,mode,clear);
                }
            }
        }
        cell_index();
    };

    merge_cells=function(cl,idx,pos1,pos2,mode,clear){
        var span=0,id,fc,c,i;
        fc=(mode==='v')?cl[pos1+'-'+idx]:cl[idx+'-'+pos1];
        for(i=pos1+1;i<pos2;i++){
            id=(mode==='v')?(i+'-'+idx):(idx+'-'+i);
            if(cl[id]){
                c=cl[id];
                span+=(mode==='v')?c.rowSpan:c.colSpan;
                relocate(c,fc);
                c.parentNode.deleteCell(c.cellIndex);
            }
        }

        if(fc!==undefined){
            if(mode==='v'){
                fc.rowSpan+=span;
            }else{
                fc.colSpan+=span;
            }

            if(clear===true||clear===undefined){
                mark(false,fc);
            }
        }
    };

    max_cols=function(table){
        var tr=table.rows,span,max=0,i,j;
        if(typeof(table)==='string'){
            table=document.getElementById(table);
        }

        for(i=0;i<tr.length;i++){
            span=0;
            for(j=0;j<tr[i].cells.length;j++){
                span+=tr[i].cells[j].colSpan||1;
            }
            if(span>max){
                max=span;
            }
        }
        return max;
    };

    split=function(mode,table){
        var tbl,tr,c,cl,rs,n,cols,max,t,i,j,get_rowspan;

        get_rowspan=function(c,row,col){
            var rs,last,i;
            rs=0;
            last=row+c.rowSpan-1;
            for(i=col-1;i>=0;i--){
                if(cl[last+'-'+i]===undefined){
                    rs++;
                }
            }
            return rs;
        };
    
        remove_selection();
        tbl=(table===undefined)?tables:get_table(table);

        for(t=0;t<tbl.length;t++){
            cl=cell_list(tbl[t]);
            max=max_cols(tbl[t]);
            tr=tbl[t].rows;
            for(i=0;i<tr.length;i++){
                cols=(mode==='v')?max:tr[i].cells.length;
                for(j=0;j<cols;j++){
                    if(mode==='v'){
                        c=cl[i+'-'+j];
                        if(c!==undefined){
                            c.redips=c.redips||{};
                        }

                        if(c!==undefined&&c.redips.selected===true&&c.rowSpan>1){
                            rs=get_rowspan(c,i,j);
                            n=tr[i+c.rowSpan-1].insertCell(j-rs);
                            n.colSpan=c.colSpan;
                            c.rowSpan-=1;
                            cell_init(n);
                            cl=cell_list(tbl[t]);
                        }
                    }else{
                        c=tr[i].cells[j];
                        c.redips=c.redips||{};
                        if(c.redips.selected===true&&c.colSpan>1){
                            cols++;
                            n=tr[i].insertCell(j+1);
                            n.rowSpan=c.rowSpan;
                            c.colSpan-=1;
                            cell_init(n);
                        }
                    }

                    if(c!==undefined){
                        mark(false,c);
                    }
                }
            }
        }
        cell_index();
    };

    get_table=function(table){
        var tbl=[];
        if(table!==undefined){
            if(typeof(table)==='string'){
                table=document.getElementById(table);
            }
            if(table&&typeof(table)==='object'&&table.nodeName==='TABLE'){
                tbl[0]=table;
            }
        }
        return tbl;
    };

    row=function(table,mode,index){
        var nc,nr=null,fr,c,cl,cols=0,i,j,k;
        remove_selection();

        if(typeof(table)!=='object'){
            table=document.getElementById(table);
        }

        if(index===undefined){
            index=-1;
        }

        if(mode==='insert'){
            fr=table.rows[0];
            for(i=0;i<fr.cells.length;i++){
                cols+=fr.cells[i].colSpan;
            }

            nr=table.insertRow(index);
            for(i=0;i<cols;i++){
                nc=nr.insertCell(i);
                cell_init(nc);
            }
            cell_index();
        }else{
            if(table.rows.length===1){
                return;
            }

            table.deleteRow(index);
            cl=cell_list(table);
            index=table.rows.length-1;
            cols=max_cols(table);
            for(i=0;i<cols;i++){
                c=cl[index+'-'+i];
                if(c===undefined){
                    for(j=index,k=1;j>=0;j--,k++){
                        c=cl[j+'-'+i];
                        if(c!==undefined){
                            c.rowSpan=k;
                            break;
                        }
                    }
                }else if(c.rowSpan>1){
                    c.rowSpan-=1;
                }
                i+=c.colSpan-1;
            }
        }
        return nr;
    };

    column=function(table,mode,index){
        var c,idx,nc,i;
        remove_selection();
        if(typeof(table)!=='object'){
            table=document.getElementById(table);
        }

        if(index===undefined){
            index=-1;
        }

        if(mode==='insert'){
            for(i=0;i<table.rows.length;i++){
                nc=table.rows[i].insertCell(index);
                cell_init(nc);
            }
            cell_index();
        } else{
            c=table.rows[0].cells;
            if(c.length===1&&(c[0].colSpan===1||c[0].colSpan===undefined)){
                return;
            }

            for(i=0;i<table.rows.length;i++){
                if(index===-1){
                    idx=table.rows[i].cells.length-1;
                }else{
                    idx=index;
                }

                c=table.rows[i].cells[idx];

                if(c.colSpan>1){
                    c.colSpan-=1;
                }else{
                    table.rows[i].deleteCell(index);
                }            
                i+=c.rowSpan-1;
            }
        }
    };

    mark=function(flag,el,row,col){
        var cl;
        if(typeof(flag)!=='boolean'){
            return;
        }

        if(typeof(el)==='string'){
            el=document.getElementById(el);
        }else if(typeof(el)!=='object'){
            return;
        }

        if(el.nodeName==='TABLE'){
            cl=cell_list(el);
            el=cl[row+'-'+col];
        }

        if(!el||el.nodeName!=='TD'){
            return;
        }

        el.redips=el.redips||{};
        if(typeof(REDIPS.table.color.cell)==='string'){
            if(flag===true){
                el.redips.background_old=el.style.backgroundColor;
                el.style.backgroundColor=REDIPS.table.color.cell;
            }else{
                el.style.backgroundColor=el.redips.background_old;
            }
        }
        el.redips.selected=flag;
    };

    remove_selection=function(){
        if(window.getSelection){
            window.getSelection().removeAllRanges();
        }else if(document.selection&&document.selection.type==="Text"){
            try{document.selection.empty();
            }
            catch(error){
            }
        }
    };

    cell_list=function(table){
        var matrix=[],matrixrow,lookup={},c,ri,rowspan,colspan,firstAvailCol,tr,i,j,k,l;
        tr=table.rows;
        for(i=0;i<tr.length;i++){
            for(j=0;j<tr[i].cells.length;j++){
                c=tr[i].cells[j];
                ri=c.parentNode.rowIndex;
                rowspan=c.rowSpan||1;
                colspan=c.colSpan||1;
                matrix[ri]=matrix[ri]||[];
                for(k=0;k<matrix[ri].length+1;k++){
                    if(typeof(matrix[ri][k])==='undefined'){
                        firstAvailCol=k;
                        break;
                    }
                }
                lookup[ri+'-'+firstAvailCol]=c;
                for(k=ri;k<ri+rowspan;k++){
                    matrix[k]=matrix[k]||[];
                    matrixrow=matrix[k];
                    for(l=firstAvailCol;l<firstAvailCol+colspan;l++){
                        matrixrow[l]='x';
                    }
                }
            }
        }
        return lookup;
    };

    relocate=function(from,to){
        var cn,i,j;
        if(from===to){
            return;
        }

        cn=from.childNodes.length;
        for(i=0,j=0;i<cn;i++){
            if(from.childNodes[j].nodeType===1){
                to.appendChild(from.childNodes[j]);
            }else{
                j++;
            }
        }
    };

    cell_index=function(flag){
        if(flag===undefined&&show_index!==true){
            return;
        }

        if(flag!==undefined){
            show_index=flag;
        }

        var tr,c,cl,cols,i,j,t;
        for(t=0;t<tables.length;t++){
            tr=tables[t].rows;
            cols=max_cols(tables[t]);
            cl=cell_list(tables[t]);
            for(i=0;i<tr.length;i++){
                for(j=0;j<cols;j++){
                    if(cl[i+'-'+j]){
                        c=cl[i+'-'+j];
                        c.innerHTML=(show_index)?i+'-'+j:'';
                    }
                }
            }
        }
    };

    return{
        
color:color,mark_nonempty:mark_nonempty,onmousedown:onmousedown,mark:mark,merge:merge,split:split,
row:row,column:column,cell_index:cell_index,cell_ignore:cell_ignore
    };
}
());

if(!REDIPS.event){
    REDIPS.event=(function(){
        var add,remove;
        add=function(obj,eventName,handler){
            if(obj.addEventListener){
                obj.addEventListener(eventName,handler,false);
            }else if(obj.attachEvent){
                obj.attachEvent('on'+eventName,handler);
            }else{
                obj['on'+eventName]=handler;
            }
        };
        remove=function(obj,eventName,handler){
            if(obj.removeEventListener){
                obj.removeEventListener(eventName,handler,false);
            }else if(obj.detachEvent){
                obj.detachEvent('on'+eventName,handler);
            }else{
                obj['on'+eventName]=null;
            }
        };
        return{
            add:add,remove:remove
        };
    }
    ());
}



제목 작성자 날짜 조회
css grid 추가/ 삭제/ 합치기/ 나누기 기능 좀 개발해 주실 수 있을.. autodoc 2018-07-05 475

 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})