후원회원 가입 받을 때 서명(싸인, 사인) 받는 법 2 - 복수의 패드 및 해당 확장변수가 필수/선택일 경우를 모두 고려함
지난번에 게시판 모듈 스킨(특히, 스케치북)을 이용해 서명 그리기를 끼워넣는 팁을 소개해드린 바 있습니다. (아래 링크 참조)
https://xetown.com/lakepark/520085
해당 게시물에서 보시는 바와 같이 @웹지기님을 통해 서명 패드가 (1) 복수로 존재하거나 (2) 필수가 아닐 수도 있는 경우 등에 대해 피드백을 받기도 했습니다.
그래서 이 두 가지 경우를 우선적으로 고려해서 반복문과 기타 구문들을 활용해서 코드를 다시 짜봤습니다.
(오늘 낮술부터 시작해서 정신이 몽롱한 관계로 지난번처럼 자세한 설명을 못드리는 점 양해 부탁드리겠습니다)
1. 준비물 구하기
- 앞선 게시물에도 쓰긴 했지만, 다시 한번 말씀 드리겠습니다.
- 일단 http://www.jqueryscript.net/other/Smooth-Signature-Pad-Plugin-with-jQuery-Html5-Canvas.html로 갑니다.
- Download 받으세요.
- jquery.signaturepad.css 파일은 css 폴더에 저장해줍니다. (스케치북 스킨의 css 폴더를 말하는 거예요)
- numeric-1.2.6.min.js, bezier.js, jquery.signaturepad.js, js/json2.min.js 등의 파일은 js 폴더에 저장해줍니다. (마찬가지로 스케치북 스킨의 js 폴더)
- 그러면, 확장변수를 만들어보겠습니다.
2. 확장변수 만들기
- 게시판 관리 > 사용자 정의 > 추가로 들어가서 확장변수를 만듭니다.
- 여기서 '사용자 정의 이름'을 signature1로 합니다. (♦반드시 그렇게 하셔야만 소스가 제대로 돌아갑니다)
- '입력항목 이름'은 원하시는 대로 하세요. 저는 그냥 '서명'이라고 했습니다.
- '입력형식'은 무엇으로 하든 관계가 없으니 가급적이면 그냥 내버려둡니다 ㅋ
- 서명은 필수일 테니 '필수항목'에선 '예'를 체크합니다.
- '설명'은 대강 이렇게 해보죠. '윗칸에 서명을 그려 넣어주세요.'
- '검색'은 '아니오'를 권장합니다.
- 그리고 서명패드를 두 개 이상으로 추가하고 싶으시다면, 순차적으로 signature2, signature3, signature4, ... 등으로 순번을 지켜주시면 됩니다.
3. write_form.html 수정
- 스킨 폴더에서 write_form.html 파일을 꺼낸 뒤 수정을 시작합니다.
- 첫 번째. 파일 상단 부분에 보면 <form action="/" method="post" onsubmit="return procFilter(this, window.insert)" class="bd_wrt bd_wrt_main clear">라는 곳이 있을 겁니다. 얘를 다음과 같이 바꿔주세요.
if(count($extra_keys)):
foreach($extra_keys as $val):
$eids[] = $val->eid;
endforeach;
endif;
}
<form action="/" method="post" onsubmit="<!--@if(strpos($eids,'signature')!==false)-->dataURL();<!--@end-->return procFilter(this, window.insert)" class="bd_wrt bd_wrt_main clear">
- 이렇게 해야 확장변수 목록 중에 'signature'가 들어가 있는 경우에만 서명 입력 부분이 문자열로 변환돼서 서버에 전달이 됩니다. 그림이 안 그려지면요? 해당 변수가 필수인 경우에는 "서명 값은 필수입니다." 같은 경고창이 뜨면서 문서 등록이 중지되겠고, 선택인 경우에는 아무런 값도 전달하지 않은 채로 문서가 등록될 겁니다.
- 두 번째, 잘 찾아보시면 <table cond="count($extra_keys)" class="et_vars exForm bd_tb">이라는 부분이 있을 겁니다. 이게 바로 확장변수 입력하는 테이블이에요.
- 그 아래아래에 <tr loop="$extra_keys=>$key,$val"> 같은 태그가 있을 겁니다. 얘를 아래와 같이 수정해봅니다. 이렇게 하면 확장변수값을 입력하는 테이블은 서명 패드(들)만 빼고 입력 폼을 띄우게 됩니다.
<tr loop="$extra_keys=>$key,$val" cond="substr($val->eid,0,9)!='signature'">
- 세 번째, 마지막으로 하나 더. 확장변수 입력 table 태그 뒤에 본격적으로 서명 부분 코딩을 시작합니다. 대략 아래와 같이 해보겠습니다.(이번에는 지난번과 달리 한번에 쭉 갑니다ㅎㅎ)
<block cond="strpos($eids,'signature')!==false">
<load target="css/jquery.signaturepad.css" />
<load target="js/numeric-1.2.6.min.js" />
<load target="js/bezier.js" />
<load target="js/jquery.signaturepad.js" />
<load target="js/json2.min.js" />
{@ $i=1; }
<div class="sigPad" style="width:296px; display:table; margin:0 auto;" loop="$extra_keys=>$key,$val" cond="substr($val->eid,0,9)=='signature'">
<ul class="sigNav">
<h3>{$val->name}<em cond="$val->is_required=='Y'">*</em></h3>
<li class="clearButton"><a href="#clear">{$lang->reload}</a></li>
</ul>
<div class="sig sigWrapper" style="height:100px;">
<div class="typed"></div>
<canvas class="pad" id="cy-sig{$i}" width="294" height="100"></canvas>
<input type="hidden" name="extra_vars{$key}" id="cy-sig_data{$i}" class="output<!--@if($val->is_required=='Y')--> cy-req<!--@end-->" value="{$oDocument->getExtraEidValue($val->eid)}">
</div>
<p style="margin-top:5px;text-align:center;font-size:11px;">{$val->desc}</p>
{@ $i++ ;}
</div>
<script>
// 서명 옵션 설정
jQuery(document).ready(function(){
jQuery('.sigPad').signaturePad({
drawOnly:true,
drawBezierCurves:true,
lineTop:90
});
});
// 서명 패드 갯수(=n-1) 자동 설정
var n = '{$i}';
// 서명 관련 변수 정의
for(var i=1;i<n;i++) {
eval('canvas'+i+'=document.getElementById("cy-sig'+i+'")'),
eval('context'+i+'=canvas'+i+'.getContext("2d")'),
eval('cv_data'+i+'=document.getElementById("cy-sig_data'+i+'")'),
eval('req'+i+'=cv_data'+i+'.className.split(" ")[1]'),
eval('val'+i+'=cv_data'+i+'.value');
}
// 서명 이미지값 문자열 전달 처리
function dataURL(){
for(var i=1;i<n;i++) {
if(eval('cv_data'+i).value != ''){
eval('cv_data'+i).value = eval('canvas'+i).toDataURL();
} else {
if(eval('req'+i) == 'cy-req') {
return false;
} else eval('cv_data'+i).value = '';
}
}
}
// 수정시 서명 문자열의 이미지 로드
if(window.addEventListener) {
for(var i=1;i<n;i++) {
if(eval('val'+i) != '') window.addEventListener('load', cnvs2Img, false);
}
function cnvs2Img(){
for(var i=1;i<n;i++) {
eval('image'+i+' = new Image()');
eval('image'+i).src = eval('val'+i);
eval('image'+i).onload = function(){
for(var i=1;i<n;i++) {
eval('context'+i).drawImage(eval('image'+i),0,0);
if(eval('val'+i) != '') {
eval('cv_data'+i).value = eval('canvas'+i).toDataURL();
} else {
eval('cv_data'+i).value = '';
}
}
}
}
}
}
</script>
</block>
4. _read.html 수정
- 주지하시듯, 게시물 본문은 _read.html. 따라서 확장변수로서 signature1~n도 여기서 일람해볼 수 있습니다. 다만, 서버로 전달된 복잡한 문자열을 다른 확장변수처럼 바로 출력할 순 없겠죠.
- 여기서 <caption class="blind">Extra Form</caption>라는 구문이 들어간 두 개의 table을 볼 수 있을 겁니다. '스킨 설정 > 본문 일반 설정 > 확장변수 위치'가 '본문 안에(기본)'인 경우엔 아래쪽 table, '제목 아래'인 경우엔 윗쪽 table이 될 겁니다.
- 이 테이블'들'에 td 태그 부분이 있습니다. 대개는 이렇게 되어 있죠. 평점 매기는 게시판을 구분 하기 위한 코드들인 거 같네요.
<td cond="$val->eid!='rating'">{$val->getValueHTML()}</td>
< td cond="$val->eid=='rating'" class="rating"><span class="starRating" title="{$val->getValueHTML()}{$lang->score}"><span style="width:{$val->getValueHTML()*10}%">{$val->getValueHTML()}</span></span></td>
- 위의 코드'들'을 다음과 같이 바꿔줍니다. 네, 바로 두 번째 줄이 핵심입니다. 서명 변수(들)에 한해서 이미지로 불러오는 거죠. 입력되어 있는 값은 이미지의 dataURL이니까요ㅎㅎ
<td cond="$val->eid!='rating'&&substr($val->eid,0,9)=='signature'"><img src="{$val->getValueHTML()}" /></td>
<td cond="$val->eid=='rating'&&substr($val->eid,0,9)!='signature'" class="rating"><span class="starRating" title="{$val->getValueHTML()}{$lang->score}"><span style="width:{$val->getValueHTML()*10}%">{$val->getValueHTML()}</span></span></td>
이상입니다.

댓글 14
.
cms후원받는 분들은 요새 꼭 필요한걸겁니다.
cms 이용이 조건이 까다롭지는 않나 보네요.
암튼 저렇게 받은 걸 pdf로 출력해서 담당자에게 전달하면 알아서 잘 처리하더라구요ㅎㅎ
ExtendKR님이 만들고 착한인연님이 수정하신 애드온도 있으니 그쪽이 더 간편할 겁니다!
https://xetown.com/lakepark/527360
댓글 서명은 힘들거 같아 본문 내에 서명을 만들려고 하는데요.
문서를 클릭해서 보고 바로 확인자 서명을 하려고 하는데요.
본문에서 바로 확인자 서명을 하면 문서 보기(read)에 서명 바로 밑에 또 확인자 서명이 생기게 하려구요.
기초지식이 없어서 잘 안되네요. 텍스트는 되는데 서명 이미지는 안되네요.
아래 스크립트 내용 적으니 수정 좀 부탁드려도 될까요??
_read.html 파일입니다. (확장변수는 sign으로 했습니다. 서명자와 확인자 구분을 위해)
<!--//본문내 서명 추가-->
<block cond="$logged_info->member_srl==$oDocument->get('member_srl')||$grant->manager">
<block cond="$click">
{@
$oDB = &DB::getInstance();
$sql = $oDB->_query('SELECT COUNT(*) as count FROM xe_document_extra_vars WHERE document_srl='.$document_srl.' and module_srl ='.$module_info->module_srl.' and eid="sign"');
$rec_count = $oDB->_fetch($sql);
}
<!--@if($rec_count->count==0)-->
{@
$query = $oDB->_query('INSERT INTO xe_document_extra_vars (module_srl, document_srl,var_idx,lang_code,value,eid) VALUES ('.$module_info->module_srl.','.$document_srl.',4,"ko","'.$click.'","sign")');
}
<!--@else-->
{@
$query = $oDB->_query('update xe_document_extra_vars set value = "'.$click.'" where document_srl = '.$document_srl.' and module_srl = '.$module_info->module_srl.' and eid = "sign"');
}
<!--@end-->
<script>location.href="{str_replace('amp;', '', getUrl('click', ''))}"</script>
</block>
<!--// 서명 받기 -->
<cond="strpos($eids,'signature')!==false">
<load target="css/jquery.signaturepad.css" />
<load target="js/numeric-1.2.6.min.js" />
<load target="js/bezier.js" />
<load target="js/jquery.signaturepad.js" />
<load target="js/json2.min.js" />
{@ $i=1; }
<div class="sigPad" style="width:296px; display:table; margin:0 auto;" loop="$extra_keys=>$key,$val" cond="substr($val->eid,0,9)=='sign'">
<ul class="sigNav">
<h3>{$val->name}<em cond="$val->is_required=='Y'">*</em></h3>
<li class="clearButton"><a href="#clear">{$lang->reload}</a></li>
</ul>
<div class="sig sigWrapper" style="height:100px;">
<div class="typed"></div>
<canvas class="pad" id="cy-sig{$i}" width="294" height="100"></canvas>
<input type="hidden" name="extra_vars{$key}" id="cy-sig_data{$i}" class="output<!--@if($val->is_required=='Y')--> cy-req<!--@end-->" value="{$oDocument->getExtraEidValue($val->eid)}">
</div>
<p style="margin-top:5px;text-align:center;font-size:11px;">{$val->desc}</p>
{@ $i++ ;}
</div>
<script>
// 서명 옵션 설정
jQuery(document).ready(function(){
jQuery('.sigPad').signaturePad({
drawOnly:true,
drawBezierCurves:true,
lineTop:90
});
});
// 서명 패드 갯수(=n-1) 자동 설정
var n = '{$i}';
// 서명 관련 변수 정의
for(var i=1;i<n;i++) {
eval('canvas'+i+'=document.getElementById("cy-sig'+i+'")'),
eval('context'+i+'=canvas'+i+'.getContext("2d")'),
eval('cv_data'+i+'=document.getElementById("cy-sig_data'+i+'")'),
eval('req'+i+'=cv_data'+i+'.className.split(" ")[1]'),
eval('val'+i+'=cv_data'+i+'.value');
}
// 서명 이미지값 문자열 전달 처리
function dataURL(){
for(var i=1;i<n;i++) {
if(eval('cv_data'+i).value != ''){
eval('cv_data'+i).value = eval('canvas'+i).toDataURL();
} else {
if(eval('req'+i) == 'cy-req') {
return false;
} else eval('cv_data'+i).value = '';
}
}
}
// 수정시 서명 문자열의 이미지 로드
if(window.addEventListener) {
for(var i=1;i<n;i++) {
if(eval('val'+i) != '') window.addEventListener('load', cnvs2Img, false);
}
function cnvs2Img(){
for(var i=1;i<n;i++) {
eval('image'+i+' = new Image()');
eval('image'+i).src = eval('val'+i);
eval('image'+i).onload = function(){
for(var i=1;i<n;i++) {
eval('context'+i).drawImage(eval('image'+i),0,0);
if(eval('val'+i) != '') {
eval('cv_data'+i).value = eval('canvas'+i).toDataURL();
} else {
eval('cv_data'+i).value = '';
}
}
}
}
}
}
</script>
<div><p align="right">
<input type='image' src="/img/footprint.png" onClick="location.href='{getUrl('click',$val->getValueHTML())}'" />
</div></p>
</block>
그나저나 코드만 봐서는 저도 잘 몰라요ㅜ
소스코드를 코드하이라이터(?) 등으로 보기 좋게 재구성한 뒤, 질문게시판에 별도 게시물로 남기시거나 제작의뢰를 하시는 게 좋을 것 같습니다.