반응형

체크박스가 포함된 게시판형태의 데이터들을 다루다보면 전체 선택 해제 기능이 자주 들어갑니다.

전체 선택에 따른 하위 체크박스들을 선택하거나 해제하고 전체박스가 선택된 상태에서 하위 체크박스를 해제하면 전체체크박스의 상태값도 해제되도록 변경되는 예제를 진행해보겠습니다.

 

체크박스 전체 선택, 해제 제어하기

allcheckbox.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<body>
    <table>
        <tr>
            <th>
                <input type="checkbox" name="check" class="allcheck">
            </th>
            <th>순번</th>
            <th>제목</th>
        </tr>
        <tr>
            <td><input type="checkbox" name="check"></td>
            <td>1</td>
            <td>제목입니다.</td>
        </tr>
        <tr>
            <td><input type="checkbox" name="check"></td>
            <td>2</td>
            <td>제목입니다.</td>
        </tr>
        <tr>
            <td><input type="checkbox" name="check"></td>
            <td>3</td>
            <td>제목입니다.</td>
        </tr>
        <tr>
            <td><input type="checkbox" name="check"></td>
            <td>4</td>
            <td>제목입니다.</td>
        </tr>
    </table>
</body>
</html>

css

*{margin:0;padding:0;}
table{width:800px;text-align:center;border-collapse:collapse;border-left:1px solid #ddd;border-right: 1px solid #ddd;}
table tr{border-bottom: 1px solid #ddd;}

JS

$(function(){
    $("[type=checkbox][name=check]").on("change", function(){ //0
        var check = $(this).prop("checked"); //1
        //전체 체크
        if($(this).hasClass("allcheck")){ //2
            $("[type=checkbox][name=check]").prop("checked", check);

        //단일 체크
        }else{ //3
            var all = $("[type=checkbox][name=check].allcheck");
            var allcheck = all.prop("checked")
            if(check != allcheck){ //3-1
                var len = $("[type=checkbox][name=check]").not(".allcheck").length; //3-2
                var ckLen = $("[type=checkbox][name=check]:checked").not(".allcheck").length; //3-2
                if(len === ckLen){ //3-3
                    all.prop("checked", true);
                }else{
                    all.prop("checked", false);
                }
            }
        }
    });
});

저는 모든 체크박스의 이름을 check로 두었고 전체선택기능의 체크박스와 일반체크박스를 class에 allcheck라는 이름으로 구분하였습니다.

 

주석번호와 매칭하여 설명을 확인하시면 됩니다.

0. jQuery를 활용하여 페이지가 로드되면 체크박스에 이벤트를 추가합니다.

1. input type이 checkbox이면서 name값이 check인 요소에 change 이벤트가 발생하면 현재 발생한 요소의 checked 값을 받아옵니다.

2. 이벤트가 발생한 요소의 클래스에 allcheck가 존재하면 전체 체크박스로 판단하고 전체 체크를 진행합니다.

(해제가 되었으면 전부다 해제, 선택이면 전부 다 선택 처리이므로 자신의 상태값과 맞춰줍니다.) 

3. 단일 체크일 경우

   3-1. 전체 체크박스의 상태값과 자신의 상태값을 비교합니다. 상태가 다를 경우 확인 작업이 필요합니다.

   3-2. 페이지에 노출된 체크 박스의 개수와 체크된 개수가 같은지 확인을 하기 위해 값을 가져옵니다.

         여기서 .not()메소드를 사용하여 전체 체크박스는 제외하였습니다.

   3-3. 가져온 개수가 서로 같다면 전체가 이미 선택된 것이므로 전체체크박스에도 선택처리를 합니다.

         반대의 경우 전체가 체크된게 아니므로 전체체크박스에 해제처리를 합니다.

 

동작 결과

잘 동작한다!

반응형
반응형

웹 페이지를 제작하면서 아주 편리하게 사용하는 alert, confirm창을 차별점을 두기 위해 디자인하고 팝업 형태로 제작의뢰가 들어오는 경우가 종종 있습니다.

 

사실 alert경우에는 동작하면 모든 javascript가 멈춘다는 특징외에는 출력메시지로 간단하게 경고 박스 띄우는 정도이기에 구현하는데 어려움은 없지만 confirm의 경우 확인, 취소버튼이 존재하며 확인이 눌린 경우 이후의 행위를 정의해야 하기에 callback 형태로 구현을 해야합니다.

 

아무래도 동작을 위해 modal의 태그와 css를 어느정도는 집어넣어야 하는 번거로움이 있지만 적용을 하고 나면 이후에 개인적인 취향으로 커스텀이 가능해집니다.

 

아래는 제가 작성해본 alert, confirm을 동작시키는 메소드와 예제입니다.(prompt도 존재하지만 개인적으로 사용하지 않아서 구성하지 않았습니다.)

 

Confirm, Alert 동작 메소드 정의하기

/**
 *  alert, confirm 대용 팝업 메소드 정의 <br/>
 *  timer : 애니메이션 동작 속도 <br/>
 *  alert : 경고창 <br/>
 *  confirm : 확인창 <br/>
 *  open : 팝업 열기 <br/>
 *  close : 팝업 닫기 <br/>
 */ 
var action_popup = {
    timer : 500,
    confirm : function(txt, callback){
        if(txt == null || txt.trim() == ""){
            console.warn("confirm message is empty.");
            return;
        }else if(callback == null || typeof callback != 'function'){
            console.warn("callback is null or not function.");
            return;
        }else{
            $(".type-confirm .btn_ok").on("click", function(){
                $(this).unbind("click");
                callback(true);
                action_popup.close(this);
            });
            this.open("type-confirm", txt);
        }
    },

    alert : function(txt){
        if(txt == null || txt.trim() == ""){
            console.warn("confirm message is empty.");
            return;
        }else{
            this.open("type-alert", txt);
        }
    },

    open : function(type, txt){
        var popup = $("."+type);
        popup.find(".menu_msg").text(txt);
        $("body").append("<div class='dimLayer'></div>");
        $(".dimLayer").css('height', $(document).height()).attr("target", type);
        popup.fadeIn(this.timer);
    },

    close : function(target){
        var modal = $(target).closest(".modal-section");
        var dimLayer;
        if(modal.hasClass("type-confirm")){
            dimLayer = $(".dimLayer[target=type-confirm]");
            $(".type-confirm .btn_ok").unbind("click");
        }else if(modal.hasClass("type-alert")){
            dimLayer = $(".dimLayer[target=type-alert]")
        }else{
            console.warn("close unknown target.")
            return;
        }
        modal.fadeOut(this.timer);
        setTimeout(function(){
            dimLayer != null ? dimLayer.remove() : "";
        }, this.timer);
    }
}

action_popup 변수에 객체 기반의 메소드화로 구현하였습니다.

timer 속성은 모달이 노출되거나 닫힐때, 자연스러운 처리를 위한 애니메이션 속도이며

confirm 메소드는 confirm효과의 모달을 동작하는 메소드로 첫번째 파라미터는 노출시킬 텍스트, 두번째 파라미터는 callback을 정의합니다.

alert 메소드는 alert 효과의 모달을 동작시켜줍니다. 파라미터는 노출시킬 텍스트만 입력합니다.

open, close 메소드는 모달을 열고 닫는 처리를 위해 정의하였습니다.

 

간단한 설명은 이정도로 하고 사용 예제 및 결과는 아래를 참고해주세요.

 

사용 예제 소스 및 결과

See the Pen Alert And Confirm Custom by myhappyman (@myhappyman) on CodePen.

 

css와 사용을 위한 display: none처리된 모달형태의 태그들을 심어두고 요청에 따라 모달을 노출하는 형태입니다.

 

 

결과

반응형
반응형

xhr(XMLHttpRequest) 객체는 서버와 데이터를 확인하기 위해 사용됩니다.

 

ajax또한 xhr 규격을 사용하여 동작하고 있고, 다양한 메소드를 통해 요청의 상태값이나 시간, 결과, 진행상태 등을 확인 할 수 있습니다.

 

여기서 xhr의 upload.onprogress 메소드를 사용하여 파일의 업로드 진행상황을 확인하고 UI적으로 페이지 진행상태를 표현 할 수 있습니다.

 

대량의 파일이나 다중으로 여러 파일을 넘길 때 상태를 알 수 있다보니 아무래도 기다리는데, 도움이 될 것 같습니다.

 

바로 예제를 통해 확인해 보겠습니다.

 

xhr.upload.progress

사용법 ajax로 넘길때 xhr메소드를 추가하고 내부에 upload.onprogress메소드를 추가하여 정의하고자 하는 파일 내용을 추가하면 됩니다.

xhr: function(){
	var xhr = $.ajaxSettings.xhr();
	xhr.upload.onprogress = function(e){
		var per = e.loaded * 100 / e.total;
		console.log(per);
	};
	return xhr;
},

 

 

사용예제

fileupload.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<style>
	*{margin:0;padding:0}
	.progressContainer{position:relative;width: 450px;padding:20px 10px;border: 1px solid #eee;margin-top: 15px;background:#000;height:20px;}
	.progress{position:absolute;width: calc(100% - 20px);height: 20px;}
	.progressTotal{background: #5D5D5D;border-radius: 10px;}
	.progressNow{width: calc(0% - 20px);background: #FFF;border-radius: 10px;}
	.progressPer{background: transparent; text-align:center;color:#A6A6A6;}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<body>
<h1>
	File Upload Test
</h1>

<P>  The time on the server is ${serverTime}. </P>
	<div style="width: 100%;padding: 25px;">
		<form id="fileForm" action="/upload.do" method="post" enctype="multipart/form-data">
			<input type="file" name="uploadFile" multiple>
			<button type="button" id="btn">전송</button>
		</form>
		<div class="progressContainer">
			<div class="progress progressTotal"></div>
			<div class="progress progressNow"></div>
			<div class="progress progressPer">0 %</div>
		</div>
	</div>
</body>
<script>
	$(function(){	
		$("#btn").on("click", function(){
			console.log("click Time : " + new Date);
			
			var form = $("#fileForm")[0];
			var formData = new FormData(form);
			$.ajax({
				type: "POST",
				enctype: 'multipart/form-data',
				url: "/upload.do",
				data: formData,
				processData: false,
				contentType: false,
				cache: false,
				xhr: function(){
					var xhr = $.ajaxSettings.xhr();
					xhr.upload.onprogress = function(e){
						var per = e.loaded * 100 / e.total;
						progressBar(per);
					};
					return xhr;
				},
				success: function (data) {
					console.log("SUCCESS : ", data);
				},
				error: function (e) {
					console.log("ERROR : ", e);
				}
			});
		});
	});
	
	function progressBar(per){
		if(per > 55){
			$(".progressPer").css("color", "#000");
		}
		per = per.toFixed(1);
		$(".progressPer").text(per+" %");
		$(".progressNow").css("width", "calc(" + per + "% - 20px)");
	}
</script>
</html>

btn이라는 버튼을 클릭하면 file에 존재하는 데이터를 넘기고 xhr메소드에 정의된 onprogress 메소드에 의해 결과 값을 노출 하는 예제입니다.

 

 

결과

극단적으로 퍼센트를 잘 보기위해 3천개의 텍스트파일을 업로드하는 테스트를 진행해봤습니다.

 

좀 더 자세한 xhr에 대해서는 아래 URL을 참조바랍니다.

 

developer.mozilla.org/ko/docs/Web/API/XMLHttpRequest/upload

 

XMLHttpRequest.upload

XMLHttpRequest upload 프로퍼티는 업로드 진행 상황을 모니터링 할 수 있는 XMLHttpRequestUpload 객체를 반환합니다.

developer.mozilla.org

 

반응형
반응형

Mysql 또는 Maria를 리눅스 서버에 설치하고 사용하다보면 테이블을 대소문자 구분하도록 설정이 되어 있는 경우가 있다.

 

해당 설정을 확인하는 방법은 아래 명령어를 통해 알 수 있다.

 

대소문자 구분상태 확인하기

show variables like 'lower_case_table_names';

Value값이 0이면 구분, 1이면 구분하지 않는 상태이다.

 

구분하지 않도록 설정하기 위해선 설정값을 변경하고 재기동이 필요하다.

 

설정 변경하기

vi, vim 등의 에디터를 통해 설정 파일을 먼저 열어준다.

vim /etc/my.cnf

 

설정 값 중에 [mysqld] 영역이 존재할텐데, 최하단에 아래의 설정값을 입력한다.

[mysqld]
lower_case_table_names=1

* [mysqld] 자체가 없다면 추가하고 입력하면 된다.

설정을 추가한다.

 

 

 

이후 서비스를 재기동하면 구분하지 않는 것을 볼 수 있다.

systemctl restart mariadb   #maria 재기동
service mysql restart       #mysql 재기동

1은 구분하지 않음

반응형
반응형

시작

systemctl start mariadb

 

종료

systemctl stop mariadb

 

재시작

systemctl restart mariadb

반응형
반응형

-파일 복사하기

cp 복사될파일 파일경로+파일명
ex) cp file1 /usr/local/server/file1

 

-파일 삭제하기

rm -r fileName

 

-파일 이동하기

mv 파일명 이동장소+파일명
ex) mv file1 /usr/local/file1

 

-파일 이름 바꾸기

mv 파일명 바꿀이름
#mv file1 test1

 

-tar 압축풀기

tar -xvf 압축명.tar

 

 

 

 

현재 경로 확인하기

pwd

 

접속 정보(로그인 계정 정보)

who am i

 

- IP확인하기

ifconfig

 

- 서버 날짜 시간 확인

date

 

-CMOS 시간확인

clock -r

 

-서버 메모리 보기

cat /proc/meminfo | grep 'MemTotal'

 

 

-사용 중인 포트 확인하기

netstat -tnlp

 

-동작 중인 프로세스 확인(PID까지 확인)

ps -efc | grep 프로세스명

 

-PID를 통한 프로세스 강제 종료

kill -9 PID값

 

 

-로그파일 등 실시간 출력 확인하기

tail -f 파일명

 

 

-소유권 변경

chown 소유권자:그룹식별자 디렉토리명
ex)  chwon abc:abc tomcat/

 

-하위 디렉토리까지 소유권 변경

chown -R 소유권자:그룹식별자 디렉토리명/

 

 

-http 등 통신 테스트

curl 주소

 

-서버 즉시 종료

shutdown -h now

 

-서버 재부팅

shutdown -r

 

반응형
반응형

기본적으로 하이디와 같은 툴에서 Mysql, Maria DB를 접근하여 쿼리를 날릴 때, 다중으로 delete, update, insert등을 처리 할 수 있다. mysql의 경우에는 구분자 ;(세미콜론)을 추가하여 DML 쿼리를 여러번 처리 할 수 있는데, 당연히 mybatis에서도 처리가 될 것이라고 생각하여 테스트 해봤지만 계속해서 문법 에러가 발생하였다.

 

확인을 해보니 Mybatis에 mysql연결을 할 때 옵션 설정이 필요하였다.

allowMultiQueries=true

 

 

allowMultiQueries 을 true처리해주고 DB를 연결해주면 다중으로 날려도 정상적으로 처리가 된다.

jdbc.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true

*추가적으로 적용할 옵션은 & 추가하여 처리

 

 

-Mybatis

<delete id="testDelete" parameterType="java.util.Map">
	DELETE FROM A where id = #{id};
	DELETE FROM B where id = #{id};
</delete>

 

반응형
반응형

Mysql에서 대량의 insert쿼리를 처리하는 로직부분이 있는데, 수정 과정을 통해 기존 등록된 데이터를 삭제하고 insert 쿼리가 동작하면서 해당 에러가 발생하였다.

 

에러가 발생한 서버의 설치된 mysql의 max_allowed값을 확인해보니 4MB였고, 에러는 5MB가 요청되어 발생한 에러였다.

 

서버에서 max_allowed_packet값 확인하기

show VARIABLES like '%max_allowed_packet%';

 

 

설정값 변경하기

mysql 설정 파일에 찾아가 옵션을 변경한다.

# vim /etc/my.cnf

[mysqld]
max_allowed_packet=16M

 

이후 서비스를 재기동하면, 설정값이 변경된 것을 확인 할 수 있다.

 

Mysql 상태확인 및 시작, 중지, 재시작 명령어

# service mysql start //시작
# service mysql stop  //중지
# service mysql restart //재시작
# service mysql status //상태확인
반응형