Last active
August 28, 2021 13:32
-
-
Save magicsih/cea3c423ccd083f9070897eab5502759 to your computer and use it in GitHub Desktop.
DataTable (Front-end to Back-end)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @RequestMapping(path = "/scriptingonly/list", method = RequestMethod.GET) | |
| public DataTable<Script> getScriptingOnlyList(@PathVariable("gameCode") String gameCode, @PathVariable("deviceOs") String deviceOs, @Valid DataTableParameter parameters, @RequestParam(name="search", required=false) String searchText) { | |
| LOG.debug("GameCode:{} DeviceOs:{} DataTableParameter:{} SearchText:{}", gameCode, deviceOs, parameters, searchText); | |
| DataTable<Script> scriptDataTable = scriptService.getScriptDataTable(gameCode, deviceOs, parameters, searchText); | |
| return scriptDataTable; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| div.dataTables_wrapper | |
| div.dataTables_filter { | |
| text-align: right; | |
| } | |
| div.dataTables_wrapper | |
| div.dataTables_filter label { | |
| font-weight: normal; | |
| white-space: nowrap; | |
| text-align: left; | |
| } | |
| div.dataTables_wrapper | |
| div.dataTables_filter input { | |
| margin-left: 0.5em; | |
| display: inline-block; | |
| width: auto; | |
| } | |
| div.dataTables_wrapper | |
| div.dataTables_paginate { | |
| margin: 0; | |
| white-space: nowrap; | |
| text-align: right; | |
| } | |
| .dataTables_paginate { | |
| float: right; | |
| text-align: right; | |
| } | |
| div.dataTables_wrapper | |
| div.dataTables_paginate | |
| ul.pagination { | |
| margin: 2px 0px 2px 0px; | |
| white-space: nowrap; | |
| } | |
| .dataTables_length { | |
| width: 40%; | |
| float: left; | |
| } | |
| .dataTables_filter { | |
| /* width: 30%; */ | |
| float: right; | |
| text-align: right; | |
| } | |
| .dataTables_info { | |
| width: 60%; | |
| float: left; | |
| } | |
| @media ( max-width :460px) { | |
| .dataTables_wrapper .col-sm-6 { | |
| width: 100%; | |
| margin-bottom: 5px; | |
| } | |
| .dataTables_wrapper .col-sm-6 .dataTables_filter { | |
| float: none; | |
| } | |
| th.unimportant { | |
| display: none; | |
| width: 0; | |
| height: 0; | |
| opacity: 0; | |
| visibility: collapse; | |
| } | |
| td.unimportant { | |
| display: none; | |
| width: 0; | |
| height: 0; | |
| opacity: 0; | |
| visibility: collapse; | |
| } | |
| th.littleimportant { | |
| display: none; | |
| width: 0; | |
| height: 0; | |
| opacity: 0; | |
| visibility: collapse; | |
| } | |
| td.littleimportant { | |
| display: none; | |
| width: 0; | |
| height: 0; | |
| opacity: 0; | |
| visibility: collapse; | |
| } | |
| } | |
| @media (max-width: 680px) { | |
| th.unimportant { | |
| display: none; | |
| width: 0; | |
| height: 0; | |
| opacity: 0; | |
| visibility: collapse; | |
| } | |
| td.unimportant { | |
| display: none; | |
| width: 0; | |
| height: 0; | |
| opacity: 0; | |
| visibility: collapse; | |
| } | |
| } | |
| @media ( max-width :767px) { | |
| .dataTables_length { | |
| float: none; | |
| } | |
| } | |
| .daterangepicker.xdisplay { | |
| width: 228px; | |
| } | |
| .dataTables_wrapper>.row { | |
| overflow: auto !important; | |
| } | |
| .imgTooltip { | |
| display: none; | |
| position: absolute; | |
| } | |
| .round { | |
| border-radius: 5px; | |
| border: 1px solid #d2d4d2; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <div id="datatableScriptingOnly"> | |
| <div id="datatable-buttons_wrapper" class="dataTables_wrapper form-inline dt-bootstrap no-footer" > | |
| <!-- 좌측 상단 --> | |
| <div class="dt-buttons btn-group"> | |
| <select class="form-control paging input-sm" id="selectPaging"> | |
| <option value="10">10행씩</option> | |
| <option value="20">20행씩</option> | |
| <option value="50">50행씩</option> | |
| </select> | |
| </div> | |
| <!-- 우측 상단 --> | |
| <div id="datatable-buttons" class="dataTables_filter"> | |
| <label><input type="search" class="form-control input-sm" placeholder="Search..." aria-controls="datatable-buttons"></label> | |
| </div> | |
| <!-- 테이블 영역 --> | |
| <table class="table table-striped table-bordered"> | |
| <thead> | |
| <tr> | |
| <th data-column="DISPLAY_NAME">이름</th> | |
| <th data-column="SCRIPT_DESCRIPTION">설명</th> | |
| <th data-column="UPDATE_DATETIME">수정일</th> | |
| <th>액션</th> | |
| </tr> | |
| </thead> | |
| <tbody></tbody> | |
| </table> | |
| <!-- 좌측 하단 --> | |
| <div class="dataTables_info" id="datatable-buttons_info" | |
| role="status" aria-live="polite"></div> | |
| <!-- 우측 하단 페이징 영역 --> | |
| <div class="dataTables_paginate paging_simple_numbers" | |
| id="datatable-buttons_paginate"> | |
| <ul class="pagination"> | |
| <li class="paginate_button previous" id="datatble-buttons_previous"><a href="javascript:void(0);" aria-controls="datatable-buttons" tabindex="0">Previous</a></li> | |
| <li class="paginate_button next" id="datatable-buttons_next"><a href="javascript:void(0);" aria-controls="datatable-buttons" tabindex="0">Next</a></li> | |
| </ul> | |
| </div> | |
| </div> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.io.Serializable; | |
| import java.util.List; | |
| public class DataTable<T> implements Serializable { | |
| private static final long serialVersionUID = 1L; | |
| private final int pageNumber; //페이지번호 | |
| private final int pageSize; //페이지크기 | |
| private final long totalCount; //전체 행의 갯수 | |
| private final long totalPage; //전체 페이지 수 | |
| private static final int pageCount = 10; //네비게이션에 보여줄 페이지 수 | |
| private final long minPageNumber; //시작 페이지 번호 | |
| private final long maxPageNumber; //끝 페이지 번호 | |
| private final long prevPageNumber; //이전 페이지 번호 | |
| private final long nextPageNumber; //다음 페이지 번호 | |
| private final long firstPageNumber; //첫목록 | |
| private final long lastPageNumber; //끝목록 | |
| private final List<T> data; | |
| /** | |
| * @param pageNumber : 현재 페이지 번호 | |
| * @param pageSize : 한 페이지에 보여줄 아이템 수 | |
| * @param totalCount : 전체 데이터 개수 | |
| * @param data : 한 페이지에 보여줄 아이템 | |
| */ | |
| public DataTable(int pageNumber, int pageSize, long totalCount, List<T> data) { | |
| super(); | |
| this.pageNumber = pageNumber; | |
| this.pageSize = pageSize; | |
| this.totalCount = totalCount; | |
| this.data = data; | |
| this.totalPage = (long)Math.ceil((double)totalCount/(double)pageSize); | |
| double minPageNo; | |
| if(this.pageNumber % DataTable.pageCount == 0){ | |
| minPageNo = Math.floor((double)this.pageNumber / DataTable.pageCount) * DataTable.pageCount - (DataTable.pageCount-1); | |
| }else{ | |
| minPageNo = Math.floor((double)this.pageNumber / DataTable.pageCount) * DataTable.pageCount + 1; | |
| } | |
| double pageCnt = Math.ceil((double)this.totalCount/(double)this.pageSize) - minPageNo; | |
| if(pageCnt > DataTable.pageCount){ | |
| pageCnt = DataTable.pageCount - 1; | |
| } | |
| double maxPageNo = minPageNo + pageCnt; | |
| this.minPageNumber = (long) minPageNo; | |
| this.maxPageNumber = (long) maxPageNo; | |
| if(this.pageNumber <= DataTable.pageCount){ | |
| this.prevPageNumber = 0; | |
| this.firstPageNumber = 0; | |
| } else{ | |
| this.prevPageNumber = this.minPageNumber - DataTable.pageCount; | |
| this.firstPageNumber = 1; | |
| } | |
| if(this.minPageNumber + DataTable.pageCount >= this.totalPage) | |
| { | |
| this.nextPageNumber = 0; | |
| this.lastPageNumber = 0; | |
| }else{ | |
| this.nextPageNumber = this.maxPageNumber + 1; | |
| this.lastPageNumber = totalPage; | |
| } | |
| } | |
| public int getPageNumber() { | |
| return pageNumber; | |
| } | |
| public int getPageSize() { | |
| return pageSize; | |
| } | |
| public long getTotalCount() { | |
| return totalCount; | |
| } | |
| public long getTotalPage() { | |
| return totalPage; | |
| } | |
| public static int getPagecount() { | |
| return pageCount; | |
| } | |
| public long getMinPageNumber() { | |
| return minPageNumber; | |
| } | |
| public long getMaxPageNumber() { | |
| return maxPageNumber; | |
| } | |
| public long getPrevPageNumber() { | |
| return prevPageNumber; | |
| } | |
| public long getNextPageNumber() { | |
| return nextPageNumber; | |
| } | |
| public long getFirstPageNumber() { | |
| return firstPageNumber; | |
| } | |
| public long getLastPageNumber() { | |
| return lastPageNumber; | |
| } | |
| public List<T> getData() { | |
| return data; | |
| } | |
| @Override | |
| public String toString() { | |
| StringBuilder builder = new StringBuilder(); | |
| builder.append("DataTable [pageNumber=") | |
| .append(pageNumber) | |
| .append(", pageSize=") | |
| .append(pageSize) | |
| .append(", totalCount=") | |
| .append(totalCount) | |
| .append(", totalPage=") | |
| .append(totalPage) | |
| .append(", minPageNumber=") | |
| .append(minPageNumber) | |
| .append(", maxPageNumber=") | |
| .append(maxPageNumber) | |
| .append(", prevPageNumber=") | |
| .append(prevPageNumber) | |
| .append(", nextPageNumber=") | |
| .append(nextPageNumber) | |
| .append(", firstPageNumber=") | |
| .append(firstPageNumber) | |
| .append(", lastPageNumber=") | |
| .append(lastPageNumber) | |
| .append(", data=") | |
| .append(data.toString()) | |
| .append("]"); | |
| return builder.toString(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @author Ilhwan Seo | |
| * */ | |
| var DataTable = function(containerId, dataUrl, defaultRowCount, defaultOrderColumn, defaultOrder, listener, isCacheable = true, ignoreHash=false, defaultPage=1) { | |
| const SEPARATOR_HASH_TAG = '|'; | |
| var containerId = containerId; | |
| var container = jQuery(containerId); | |
| var filterContainer = jQuery(containerId); | |
| var columnCount = container.find('table thead tr').children().length; | |
| var rowCount = 0; | |
| var currentPage = 0; | |
| var dataUrl = dataUrl; | |
| var listener = listener; | |
| var orderColumn = ""; | |
| var orderAsc = ""; | |
| var filter = []; | |
| var ignoreHash = ignoreHash; | |
| var needInitHashTag = false; | |
| // 이 전에 init된 경우는 event 전부 해제한다. | |
| // TODO datatable 재활용 y/n 받아서 처리 | |
| if($(containerId).data('isInitDataTable') !== undefined && $(containerId).data('isInitDataTable')){ | |
| //1. 물려있던 이벤트 해제 | |
| $(containerId).find("*").off(); | |
| //2. search box 초기화 | |
| jQuery(containerId+' input[type="search"]').val(""); | |
| //3. hash tag 안따라가게 조건 추가 | |
| needInitHashTag = true; | |
| } | |
| $(containerId).data("isInitDataTable", true); | |
| container.ready(function() { | |
| if(window.location.hash.length > 1 && !needInitHashTag) { | |
| var encodedHashTags = window.location.hash.replace("#","").split(SEPARATOR_HASH_TAG); | |
| var foundMyContainer = false; | |
| for(var i=0;i<encodedHashTags.length;i++){ | |
| var hashtags = b64DecodeUnicode(encodedHashTags[i]).split(SEPARATOR_HASH_TAG); | |
| // console.log("hashtags : ", hashtags); | |
| //TODO hashTags length 1보다 작으면 return 하자.. | |
| var id = hashtags[0]; | |
| if(id === containerId.replace("#","")) { | |
| foundMyContainer = true; | |
| var page = hashtags[1]; | |
| var rows = hashtags[2]; | |
| var column = hashtags[3]; | |
| var order = hashtags[4]; | |
| var f = hashtags[5]; | |
| if(typeof f !== 'undefined') { | |
| var fs = f.split("&"); | |
| for(var i in fs) { | |
| var kv = fs[i].split("="); | |
| // console.log(kv); | |
| var name = kv[0]; | |
| var value = kv[1]; | |
| setFilterToDom(name, value); // Hashtag에서 추출한 filter 값을 자료구조에 세팅 | |
| } | |
| } else{ | |
| setFiltersFromSelectBox(); | |
| } | |
| setSearchOrder(column,order); | |
| setRowCount(rows); | |
| loadData(page); | |
| break; | |
| } | |
| } | |
| if(foundMyContainer === false) { | |
| setSearchOrder(defaultOrderColumn, defaultOrder); | |
| setRowCount(defaultRowCount); | |
| setFiltersFromSelectBox(); | |
| loadData(defaultPage); | |
| } | |
| } | |
| else{ | |
| setSearchOrder(defaultOrderColumn, defaultOrder); | |
| setRowCount(defaultRowCount); | |
| setFiltersFromSelectBox(); | |
| loadData(defaultPage); | |
| } | |
| }); | |
| function b64EncodeUnicode(str) { | |
| return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { | |
| return String.fromCharCode('0x' + p1); | |
| })); | |
| } | |
| function b64DecodeUnicode(str) { | |
| return decodeURIComponent(atob(str).split('').map(function(c) { | |
| return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); | |
| }).join('')); | |
| } | |
| //테이블 안에 있는 Select box로 부터 필터값을 채운다. | |
| function setFiltersFromSelectBox() { | |
| var filters = filterContainer.find('.datatable-filter'); | |
| for(var i = 0 ; i < filters.length; ++i) { | |
| var name = jQuery(filters[i]).data('filter-name'); | |
| var type = jQuery(filters[i]).data('filter-type'); | |
| var value = getFilterValues(name, type, filters[i]); | |
| filter.push({"name":name, "value":value}); | |
| } | |
| var searchColumn = jQuery(containerId+' select[type="column"]').val(); | |
| if(searchColumn !== undefined) { | |
| filter.push({"name":"searchColumn","value":searchColumn}); | |
| } | |
| var searchText = jQuery(containerId+' input[type="search"]').val(); | |
| if(searchText !== undefined) { | |
| filter.push({"name":"search","value":searchText}); | |
| } | |
| } | |
| filterContainer.find('.datatable-filter').on('change', function() { | |
| var name = jQuery(this).data('filter-name'); | |
| var type = jQuery(this).data('filter-type'); | |
| var value = getFilterValues(name, type, this); | |
| if(name === undefined || value === undefined) { | |
| return; | |
| } | |
| for(var i in filter) { | |
| if(filter[i].name === name) { | |
| filter[i] = {"name":name, "value":value}; | |
| break; | |
| } | |
| } | |
| loadData(1); | |
| }); | |
| function getFilterValues(filterName, filterType, selector) { | |
| switch(filterType) { | |
| case 'radio': | |
| return [jQuery(selector).find('input:radio[name="' + containerId.replace("#","")+'_'+filterName + '"]:checked').val()]; | |
| case 'checkbox': | |
| var values = []; | |
| var checkedInputs = jQuery(selector).find('input:checkbox[name="' + containerId.replace("#","")+'_'+filterName + '"]:checked'); | |
| for(var input of checkedInputs) { | |
| values.push(input.value); | |
| } | |
| return values; | |
| case 'hidden': | |
| return jQuery(selector).find('input:hidden[name="' + containerId.replace("#","")+'_'+filterName + '"]').val(); | |
| default: | |
| return; | |
| } | |
| } | |
| container.find('th').each(function() { | |
| var column = jQuery(this).data('column'); | |
| if(column !== undefined){ | |
| jQuery(this).css("cursor","pointer"); | |
| } | |
| else{ | |
| jQuery(this).css("cursor","auto"); | |
| } | |
| }); | |
| container.find('th').on('mouseenter', function() { | |
| var column = jQuery(this).data('column'); | |
| if(typeof column !== 'undefined') { | |
| jQuery(this).css("text-decoration","underline"); | |
| } | |
| }); | |
| container.find('th').on('mouseleave', function() { | |
| var column = jQuery(this).data('column'); | |
| if(typeof column !== 'undefined') { | |
| jQuery(this).css("text-decoration",""); | |
| } | |
| }); | |
| container.find('select.paging').on('change', function() { | |
| var rows = jQuery(this).val(); | |
| setRowCount(rows); | |
| loadData(1); | |
| }); | |
| container.find('input[type="search"]').on('keyup', function(e) { | |
| if(e.keyCode == 13) { | |
| var text = jQuery(this).val(); | |
| if(container.find('select[type="column"]') != null){ | |
| setFilterToDom("searchColumn", container.find('select[type="column"]').val()); | |
| } | |
| setFilterToDom("search",text); | |
| loadData(1); | |
| } | |
| }); | |
| container.find('li.paginate_button.previous').on('click', function() { | |
| var prev = jQuery(this).data('prev'); | |
| if(typeof prev !== 'undefined') { | |
| loadData(prev); | |
| } | |
| }); | |
| container.find('li.paginate_button.next').on('click', function() { | |
| var next = jQuery(this).data('next'); | |
| if(typeof next !== 'undefined') { | |
| loadData(next); | |
| } | |
| }); | |
| container.find('th').on('click', function() { | |
| var column = jQuery(this).data('column'); | |
| if(typeof column === 'undefined') { | |
| return; | |
| } | |
| if(typeof jQuery(this).data('order') === 'undefined') { | |
| jQuery(this).data('order', 'asc'); | |
| } else if(jQuery(this).data('order') === 'asc') { | |
| jQuery(this).parent().find("th").removeData('order'); | |
| jQuery(this).data('order','desc'); | |
| } else { | |
| //jQuery(this).data('order','asc'); | |
| if (column === defaultOrderColumn ){ | |
| jQuery(this).data('order','asc'); | |
| } | |
| else{ | |
| jQuery(this).parent().find("th").removeData('order'); | |
| } | |
| } | |
| var order = jQuery(this).data('order'); | |
| if(typeof order !== 'undefined') { | |
| setSearchOrder(column, order); | |
| loadData(currentPage); | |
| } else{ | |
| setSearchOrder(defaultOrderColumn, defaultOrder); | |
| loadData(currentPage); | |
| } | |
| }); | |
| container.find('.div-order').on('change', function(){ | |
| var orderingInfo = $(this).val(); | |
| if(typeof orderingInfo !== '') { | |
| orderingInfo = orderingInfo.split("-"); | |
| var column = orderingInfo[0]; | |
| var order = orderingInfo[1]; | |
| setSearchOrder(column, order); | |
| loadData(currentPage); | |
| } else{ | |
| loadData(currentPage); | |
| } | |
| }); | |
| container.on('click', 'ul.pagination li:not(.previous,.next,.active) a', function() { | |
| var page = jQuery(this).data('page'); | |
| Tracker.event('datatable','pagechange', containerId + "에 대한 페이지 변경:" + page); | |
| loadData(page); | |
| }); | |
| this.changePaginateClickEvent = function(func){ | |
| container.off('click', 'ul.pagination li:not(.previous,.next,.active) a'); | |
| container.on('click', 'ul.pagination li:not(.previous,.next,.active) a', func); | |
| }; | |
| function setRowCount(rows){ | |
| rowCount = rows; | |
| }; | |
| function setSearchOrder(column, order) { | |
| orderColumn = column; | |
| orderAsc = order; | |
| } | |
| //필터 배열에 값 채우기 | |
| function setFilterToDom(name, value) { | |
| var found = false; | |
| for(var i=0; i < filter.length; i++) { | |
| if(filter[i].name === name) { | |
| filter[i].value = value; | |
| found = true; | |
| break; | |
| } | |
| } | |
| if(found === false) { | |
| filter.push({"name":name, "value":value}); | |
| } | |
| switch(name) { | |
| case "searchColumn": | |
| jQuery(containerId+' select[type="column"]').val(value); | |
| break; | |
| case "search": | |
| jQuery(containerId+' input[type="search"]').val(value); | |
| break; | |
| case "status": | |
| var filterInputs = filterContainer.find('input:checkbox[name="' + containerId.replace("#","")+'_'+name+ '"]'); | |
| var checkStatuses = value.split(","); | |
| if(checkStatuses.length > 0) { | |
| for(var input of filterInputs) { | |
| if(checkStatuses.includes(input.value)) { | |
| $(input.parentElement).addClass('active'); | |
| $(input).prop('checked', true); | |
| }else { | |
| $(input.parentElement).removeClass('active'); | |
| $(input).prop('checked', false); | |
| } | |
| } | |
| } | |
| break; | |
| case "qaVersionList": | |
| jQuery(containerId+' input[name="' + containerId.replace("#","")+'_'+name+ '"]').val(value); | |
| break; | |
| default: | |
| filterContainer.find('select.filter[data-name="' + name + '"]').val(value); | |
| break; | |
| } | |
| } | |
| function setDataUrl(setUrl){ | |
| dataUrl = setUrl; | |
| } | |
| function loadData(page) { | |
| $('.div-table').empty(); // table형이 아닌 div인 경우 비워주기위해 추가했습니다 | |
| $('#image-choice-btn').prop('disabled', true); // 이미지 선택 버튼 비활성화 | |
| var hashtag = [containerId.replace("#",""), page, rowCount, orderColumn, orderAsc].join(SEPARATOR_HASH_TAG); | |
| var data = { | |
| page: page, | |
| rows: rowCount, | |
| col: orderColumn, | |
| order: orderAsc | |
| }; | |
| if(filter.length > 0) { | |
| var filterHashtag = SEPARATOR_HASH_TAG; | |
| for(var i in filter) { | |
| var value = filter[i].value; | |
| if(value != null) { | |
| // array인 경우에 query param에 추가할 때 toString()이 반드시 필요합니다. | |
| value = value.toString(); | |
| } | |
| data[filter[i].name] = value; | |
| filterHashtag += filter[i].name + "=" + data[filter[i].name]; | |
| if(i < filter.length-1) { | |
| filterHashtag += "&"; | |
| } | |
| } | |
| hashtag += filterHashtag; | |
| } | |
| // console.log("dataUrl : ", dataUrl); | |
| jQuery.ajax(dataUrl, { | |
| async : true, | |
| data: data, | |
| headers: { | |
| "Accept": "application/json", | |
| 'Content-type': 'application/json', | |
| 'Cache-Control': isCacheable? 'cache' : 'no-cache' | |
| }, | |
| beforeSend : function(jqXHR, settings) { | |
| // console.log("beforeSend data is " + JSON.stringify(data)); | |
| // container.find("tbody").empty(); | |
| // container.find('ul.pagination li.paginate_button:not(.previous,.next)').remove(); | |
| if (!ignoreHash) { | |
| if(window.location.hash.length > 0){ | |
| var finalUpdatingEncodedHashTags = ""; | |
| var encodedHashTags = window.location.hash.replace("#","").split(SEPARATOR_HASH_TAG); | |
| var foundMyContainer = false; | |
| for(var i=0;i<encodedHashTags.length;i++) { | |
| var decodedHashTags = b64DecodeUnicode(encodedHashTags[i]).split(SEPARATOR_HASH_TAG); | |
| if(decodedHashTags.length < 1) continue; | |
| var id = decodedHashTags[0]; | |
| if(id !== containerId.replace("#","")) { | |
| finalUpdatingEncodedHashTags += encodedHashTags[i]; | |
| } else { | |
| foundMyContainer = true; | |
| finalUpdatingEncodedHashTags += b64EncodeUnicode(hashtag); | |
| } | |
| if(i < encodedHashTags.length-1) { | |
| finalUpdatingEncodedHashTags += SEPARATOR_HASH_TAG; | |
| } | |
| } | |
| if(foundMyContainer === false) { | |
| finalUpdatingEncodedHashTags += SEPARATOR_HASH_TAG; | |
| finalUpdatingEncodedHashTags += b64EncodeUnicode(hashtag); | |
| } | |
| window.location.hash=finalUpdatingEncodedHashTags; | |
| } else { | |
| window.location.hash=b64EncodeUnicode(hashtag); | |
| } | |
| } | |
| }, | |
| success : function(datatable, textStatus, jqXHR) { | |
| // console.log(datatable); | |
| var data = datatable.data; | |
| var tbody = container.find("tbody"); | |
| currentPage = datatable.pageNumber; | |
| // 초기화 위치 변경 beforeSend -> afterReceive : why? 빠르게 여러번 요청 시 동시에 받으면서 여러 개의 응답이 한 번에 쌓임 | |
| container.find("tbody").empty(); | |
| container.find('ul.pagination li.paginate_button:not(.previous,.next)').remove(); | |
| if (data.length < 1) { | |
| if(typeof listener.onDataEmpty === 'function') { | |
| listener.onDataEmpty(tbody, data, rowCount); | |
| } | |
| var tr = '<tr><td colspan="' + columnCount + '" style="text-align:center;"><span class="tas-lang" lang-key="common-table-no-data"></span></td></tr>'; | |
| tbody.append(tr); | |
| TAS_LANG.setValues('common-table-no-data'); | |
| container.find('div#datatable-buttons_info').text("Page: 1 / 1 Total: 0"); | |
| } else { | |
| container.find('div#datatable-buttons_info').text("Page: " + datatable.pageNumber + " / " + datatable.maxPageNumber + " Total: " + datatable.totalCount); | |
| for(var i = datatable.minPageNumber; i <= datatable.maxPageNumber; ++i) { | |
| if(i == datatable.pageNumber) { | |
| jQuery('<li class="paginate_button active"><a href="javascript:void(0);" data-page="' + i + '" aria-controls="datatable-buttons">' + i + '</a></li>').insertBefore(container.find('ul.pagination li:last-child')); | |
| } else{ | |
| jQuery('<li class="paginate_button"><a href="javascript:void(0);" data-page="' + i + '" aria-controls="datatable-buttons">' + i + '</a></li>').insertBefore(container.find('ul.pagination li:last-child')); | |
| } | |
| } | |
| if(datatable.prevPageNumber != 0) { | |
| container.find('#datatable-buttons_previous').removeClass('disabled').data('prev', datatable.prevPageNumber); | |
| } else { | |
| container.find('#datatable-buttons_previous').addClass('disabled').removeData('prev'); | |
| } | |
| if(datatable.nextPageNumber != 0) { | |
| container.find('#datatable-buttons_next').removeClass('disabled').data('next', datatable.nextPageNumber); | |
| } else{ | |
| container.find('#datatable-buttons_next').addClass('disabled').removeData('next'); | |
| } | |
| container.find('select.paging').val(rowCount).attr("selected","selected"); | |
| container.find('th').each(function() { | |
| jQuery(this).find('i.fa').remove(); | |
| if(jQuery(this).data('column') === orderColumn) { | |
| //jQuery(this).find('i.fa').remove(); | |
| if(orderAsc === 'asc') { | |
| jQuery(this).append(' <i class="fa fa-caret-up"></i>'); | |
| } else{ | |
| jQuery(this).append(' <i class="fa fa-caret-down"></i>'); | |
| } | |
| } | |
| }); | |
| listener.onDataLoad(tbody, data, datatable); | |
| } | |
| // 전처리, 후처리 스크립트 선택 시 선택된 아이들 css 처리 | |
| if(typeof dtBeforeScripts !== 'undefined' && dtBeforeScripts !== null){ | |
| Array.from(beforeScriptSeqs).forEach(function(seq){ | |
| $("#trB"+seq).css('opacity', '0.3'); | |
| $("#trB"+seq).css('cursor', 'not-allowed'); | |
| }); | |
| } | |
| if(typeof dtAfterScripts !== 'undefined' && dtBeforeScripts !== null){ | |
| Array.from(afterScriptSeqs).forEach(function(seq){ | |
| $("#trA"+seq).css('opacity', '0.3'); | |
| $("#trA"+seq).css('cursor', 'not-allowed'); | |
| }); | |
| } | |
| }, | |
| complete : function(jqXHR, textStatus) { | |
| }, | |
| error: function(jqXHR, textStatus, errorThrown) { | |
| if(typeof listener.onDataError !== 'undefined') { | |
| listener.onDataError(textStatus); | |
| } | |
| else{ | |
| container.find("tbody").append('<tr><td colspan="' + columnCount + '" style="text-align:center;">' + errorThrown + '</td></tr>'); | |
| } | |
| } | |
| }); | |
| }; | |
| this.setRowCount = function(rows) { | |
| setRowCount(rows); | |
| }; | |
| this.setSearchOrder = function(column, order) { | |
| setSearchOrder(column, order); | |
| }; | |
| this.reloadData = function() { | |
| this.loadData(currentPage); | |
| }; | |
| this.loadData = function(page) { | |
| loadData(page); | |
| }; | |
| this.setFilterToDom = function(name, value) { | |
| setFilterToDom(name, value); | |
| } | |
| this.setDataUrl = function(url) { | |
| setDataUrl(url); | |
| }; | |
| }; | |
| Date.prototype.format = function(f) { | |
| if (!this.valueOf()) | |
| return " "; | |
| var d = this; | |
| return f.replace(/(yyyy|yy|MM|dd|E|hh|mm|ss|a\/p)/gi, function($1) { | |
| switch ($1) { | |
| case "yyyy": | |
| return d.getFullYear(); | |
| case "yy": | |
| return (d.getFullYear() % 1000).zf(2); | |
| case "MM": | |
| return (d.getMonth() + 1).zf(2); | |
| case "dd": | |
| return d.getDate().zf(2); | |
| case "HH": | |
| return d.getHours().zf(2); | |
| case "hh": | |
| return ((h = d.getHours() % 12) ? h : 12).zf(2); | |
| case "mm": | |
| return d.getMinutes().zf(2); | |
| case "ss": | |
| return d.getSeconds().zf(2); | |
| case "a/p": | |
| return d.getHours() < 12 ? "AM" : "PM"; | |
| default: | |
| return $1; | |
| } | |
| }); | |
| }; | |
| Date.prototype.setUTCEpoch = function(epoch) { | |
| var d = this; | |
| var offset = d.getTimezoneOffset() * 60 * 1000; | |
| d.setTime(epoch - offset); | |
| return d; | |
| }; | |
| String.prototype.string = function(len) { | |
| var s = '', i = 0; | |
| while (i++ < len) { | |
| s += this; | |
| } | |
| return s; | |
| }; | |
| String.prototype.zf = function(len) { | |
| return "0".string(len - this.length) + this; | |
| }; | |
| Number.prototype.zf = function(len) { | |
| return this.toString().zf(len); | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import javax.validation.constraints.Min; | |
| public class DataTableParameter { | |
| @Min(1) private int page; | |
| @Min(1) private int rows; | |
| private String col; | |
| private String order; | |
| public DataTableParameter() { | |
| } | |
| public DataTableParameter(int page, int rows) { | |
| this.page = page; | |
| this.rows = rows; | |
| } | |
| public int getPage() { | |
| return page; | |
| } | |
| public void setPage(int page) { | |
| this.page = page; | |
| } | |
| public int getRows() { | |
| return rows; | |
| } | |
| public void setRows(int rows) { | |
| this.rows = rows; | |
| } | |
| public String getCol() { | |
| return col; | |
| } | |
| public void setCol(String col) { | |
| this.col = col; | |
| } | |
| public String getOrder() { | |
| return order; | |
| } | |
| public void setOrder(String order) { | |
| this.order = order; | |
| } | |
| @Override public int hashCode() { | |
| final int prime = 31; | |
| int result = 1; | |
| result = prime * result + ((col == null) ? 0 : col.hashCode()); | |
| result = prime * result + ((order == null) ? 0 : order.hashCode()); | |
| result = prime * result + page; | |
| result = prime * result + rows; | |
| return result; | |
| } | |
| @Override public boolean equals(Object obj) { | |
| if (this == obj) | |
| return true; | |
| if (obj == null) | |
| return false; | |
| if (getClass() != obj.getClass()) | |
| return false; | |
| DataTableParameter other = (DataTableParameter) obj; | |
| if (col == null) { | |
| if (other.col != null) | |
| return false; | |
| } else if (!col.equals(other.col)) | |
| return false; | |
| if (order == null) { | |
| if (other.order != null) | |
| return false; | |
| } else if (!order.equals(other.order)) | |
| return false; | |
| if (page != other.page) | |
| return false; | |
| if (rows != other.rows) | |
| return false; | |
| return true; | |
| } | |
| @Override public String toString() { | |
| StringBuilder builder = new StringBuilder(); | |
| builder.append("page=").append(page).append("&rows=").append(rows).append("&col=").append(col) | |
| .append("&order=").append(order); | |
| return builder.toString(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.lang.reflect.Field; | |
| public class DataTableQueryParameter<T> { | |
| final Class<T> typeParameterClass; | |
| private final String gameCode; | |
| private final String deviceOs; | |
| private final int start; | |
| private final int count; | |
| private String orderColumn; | |
| private String order; | |
| private String versionName; | |
| public DataTableQueryParameter(final Class<T> typeParameterClass, final String gameCode, | |
| final String deviceOs, final DataTableParameter dataTableParameters) { | |
| super(); | |
| this.typeParameterClass = typeParameterClass; | |
| this.gameCode = gameCode; | |
| this.deviceOs = deviceOs; | |
| this.start = (dataTableParameters.getPage() - 1) * dataTableParameters.getRows(); | |
| this.count = dataTableParameters.getRows(); | |
| this.setOrder(dataTableParameters.getOrder()); | |
| this.setOrderColumn(dataTableParameters.getCol()); | |
| } | |
| public String getGameCode() { | |
| return gameCode; | |
| } | |
| public String getDeviceOs() { | |
| return deviceOs; | |
| } | |
| public int getStart() { | |
| return start; | |
| } | |
| public int getCount() { | |
| return count; | |
| } | |
| public String getOrderColumn() { | |
| return orderColumn; | |
| } | |
| private void setOrderColumn(String orderColumn) { | |
| if (orderColumn == null || orderColumn.isEmpty()) | |
| return; | |
| String replace = orderColumn.replace("_", ""); | |
| if (typeParameterClass.getSuperclass() != null) { | |
| // TODO 부모가 없을 때 까지 올라가는 로직 까지는 안 짰음 | |
| for (Field f : typeParameterClass.getSuperclass().getDeclaredFields()) { | |
| if (f.getName().equalsIgnoreCase(replace)) { | |
| this.orderColumn = orderColumn; | |
| return; | |
| } | |
| } | |
| } | |
| for (Field f : typeParameterClass.getDeclaredFields()) { | |
| if (f.getName().equalsIgnoreCase(replace)) { | |
| this.orderColumn = orderColumn; | |
| return; | |
| } | |
| } | |
| throw new RuntimeException("No match columns!"); | |
| } | |
| public void setOrderColumnManually(String orderColumn) { | |
| this.orderColumn = orderColumn; | |
| } | |
| public void setOrderManually(String order) { | |
| this.order = order; | |
| } | |
| public String getOrder() { | |
| return order; | |
| } | |
| private void setOrder(String order) { | |
| if (order == null || order.isEmpty()) | |
| return; | |
| if (order.equalsIgnoreCase("asc") || order.equalsIgnoreCase("desc")) { | |
| this.order = order; | |
| } else { | |
| throw new RuntimeException("No match column order!"); | |
| } | |
| } | |
| public String getVersionName() { return versionName; } | |
| public void setVersionName(String versionName) { this.versionName = versionName; } | |
| @Override public String toString() { | |
| return "DataTableQueryParameter [gameCode=" + gameCode + ", deviceOs=" + deviceOs + ", start=" | |
| + start + ", count=" + count + ", orderColumn=" + orderColumn + ", order=" + order | |
| + ", typeParameterClass=" + typeParameterClass + "]"; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| List<Script> selectScriptList(DataTableQueryParameter<Script> qp, String searchText); | |
| int selectTotalScriptCount(String gameCode, String deviceOs, String searchText); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <select id="selectTotalScriptCount" resultType="int"> | |
| SELECT COUNT(1) AS CNT FROM TB_SCRIPT | |
| WHERE | |
| GAME_CODE = #{0} | |
| AND | |
| DEVICE_OS = #{1} | |
| <if test="param3 != null"> | |
| AND | |
| DISPLAY_NAME LIKE '%${param3}%' | |
| </if> | |
| </select> | |
| <select id="selectScriptList" resultType="com.netmarble.tas.dashboard.domain.Script"> | |
| SELECT | |
| SCRIPT_SEQ, | |
| GAME_CODE, | |
| DEVICE_OS, | |
| DISPLAY_NAME, | |
| SCRIPT_DESCRIPTION, | |
| UPDATE_DATETIME | |
| FROM | |
| TB_SCRIPT | |
| WHERE | |
| GAME_CODE = #{param1.gameCode} | |
| AND | |
| DEVICE_OS = #{param1.deviceOs} | |
| <if test="param2 != null"> | |
| AND | |
| DISPLAY_NAME LIKE '%${param2}%' | |
| </if> | |
| <if test="param1.order != null and param1.order != '' and param1.orderColumn != null and param1.orderColumn != ''"> | |
| ORDER BY ${param1.orderColumn} ${param1.order} | |
| </if> | |
| LIMIT | |
| #{param1.start}, #{param1.count} | |
| </select> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Transactional(readOnly=true) | |
| public DataTable<Script> getScriptDataTable(final String gameCode, final String deviceOs, final DataTableParameter parameters, final String searchText) { | |
| int totalCount = scriptMapper.selectTotalScriptCount(gameCode, deviceOs, searchText); | |
| DataTableQueryParameter<Script> qp = new DataTableQueryParameter<Script>(Script.class, gameCode, deviceOs, parameters); | |
| List<Script> selectScriptList = scriptMapper.selectScriptList(qp, searchText); | |
| DataTable<Script> dt = new DataTable<Script>(parameters.getPage(), parameters.getRows(), totalCount, selectScriptList); | |
| return dt; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment