적용버전 : XE Ver 1.4 로그인 폼 만들기

로그인 폼이 필요합니다.

위젯을 이용한 로그인

로그인 위젯레이아웃에서 로그인을 실행하는 가장 편리한 방법은 로그인 위젯를 활용하는 것입니다. XE 코어에는 위젯(wiggets) 디렉터리 안에 회원정보(member) 모듈과 연동된 로그인 폼을 이미 제공하고 있습니다. 활용하는 방법은, XE 제어판 위젯 모듈에서 로그인 정보 출력에 필요한 코드를 생성하게 되면 각 속성의 설정값을 포함하는 <img /> 태그 구문을 여러분에게 내놓게 됩니다. 이미지 태그<img /> 형식을 사용하였지만 이것 역시 XE가 만들어준 XE 템플릿 구문입니다. 이 구문을 레이아웃 문서의 일정한 위치에 포함시켜 사용하게 됩니다.

위젯은 어떻게 일을 할까요? 위젯의 작동방법을 살펴보면, XE 코어는 기본적으로 웹사이트에 접속한 사람의 로그인 여부를 확인하고 만약 로그인이 되었다면 회원의 관리 정보를 $logged_info 변수에 미리 담아둡니다. 이 과정은 위젯과 상관없는 일입니다. XE 코어가 스스로 판단하는 일이지요. 그 뒤에 위젯이 참견을 합니다. "XE 형!, 이 사람 로그인 했어? 안했어?" XE는 말없이 위젯에게 $logged_info를 넘겨 줍니다. "참~나~! 말을 하면 좋잖아?" 뒤돌아서 변수를 열어보니 $logged_info="NULL", "안했네!!!" 위젯은 변수를 넘겨 받고 widgets/login_info/login_info.class.php 문서에서 정해놓은 방법대로 관리자가 정해 놓은 스킨(skin)을 찾아 로그인하지 않은 사람에게는 login_form.html 문서를, 로그인을 한 사람에게는 login_info.html 문서를 보여주는 것이지요...^^

$logged_info 변수에 값이 없는 사람에게는 로그인 할 수 있는 폼(login_form.htm) 문서를 작은 창으로 보여줍니다. 이곳에 아이디와 비밀번호를 입력하고 전송버튼을 클릭하게 되면 filter/login.xml 문서의 도움을 받아 XE 형이 가지고 있는 회원명단과 대조해 보고 없으면 에러 메시지(error message)를, 맞으면 회원의 기본 정보를 출력하는 login_info.html 문서를 보여주게 됩니다.

로그인 위젯은 무척 편리한 도구이지만 레이아웃의 형태 또는 디자인과 어울리는 스킨(skin)을 입어야 하는 문제가 있습니다. 로그인 위젯은 항상 XE 형이 물려주는 옷은 싫다고 말합니다. 형은 점잖은 스타일을 좋아하는데 로그인 위젯은 항상 색이 화려하고 언제나 튀는 옷을 좋아합니다. XE 형이 고민에 빠졌습니다. "용돈을 주고 XE 마켓에 가서 사라고 할까? 아니면 내가 직접 만들어 줄까? 아니야! 공식 홈페이지 다운로드 자료실에 가면 좋은 스킨 많은데 우선 거기부터 가서 확인해 봐야겠다!"


핸드메이드(handmade) 레이아웃 로그인

로그인 폼 XE 형과 동생 로그인 위젯이 오래간만에 XE 백화점 위젯 스킨 마켓을 구경하였습니다. 하지만 마음에 드는 스킨도 좀처럼 찾을 수 없고 이건 내 스킨이다! 하는 것들은 가격이 너무나 비쌉니다. 형은 위젯의 손을 잡아 끌면서 "그래도 다운로드 자료실이 최고야! 거기로 가보자!" 다운로드 자료실은 요즘 지하1층으로 내려왔군요. 예전에는 찾는 사람들도 무척 많았고 이것저것 물건들도 다양했는데 요즘은 모두들 마켓으로만 물건을 공급한다고 하니 조금은 한산하기까지 합니다. 로그인 위젯 동생은 벌써 심통이 났습니다. 메이커 아니면 안입겠다나? 물건은 보지도 않고 심통만 부리니 XE 형도 화가 슬슬 치밀어 올랐습니다. 결국 스킨 쇼핑을 계속할 수 없었지요.

XE 형이 로그인 위젯을 위해 직접 스킨을 만들어 주었습니다. "어이~ 동생! 이거 입을래? 내가 만든건데~" 위젯 동생은 슬쩍 보더니 "이게 뭐야! 누더기같은 걸 어떻게 입냐? 형이나 쓰세요~!" 한마디로 거절 당했습니다...^^ 메이커 아니면 안입겠다는 동생을 위해 밤새 만든 빈티지룩에 핸드메이드 로그인 위젯 스킨인데 형이나 입으라고 합니다. XE 형은 정말로 화가나서 로그인 위젯의 도움 없이 레이아웃에 사용하기로 하였습니다. XE 형은 어떻게 했을까요?


1# 로그인 위젯이 가지고 있는 xe/widgets/login_info/skins/xe_official/filter/ 에 들어있는 모든 문서를 뺏어 옵니다.

filter 디렉터리 안에는 login.xml, logout.xml, openid_login.xml 문서 3종류가 들어 있습니다.
이 중에서 login.xml 문서와 logout.xml 문서의 맨 윗줄에 있는 <filter name="widget_login" 이 부분을 찾아 name="login" 이라고 수정합니다. 더이상 위젯이 하는 일이 아니라고 바꿔주는 것이지요. XE 형은 대단히 화가 났던 모양입니다. 문서만 뺏어오는 것이 아니라 filter 디렉터리 전체를 레이아웃 디렉터리로 가져와야 합니다.


2# 레이아웃에서 로그인 여부에 따라 보여줄 내용을 구분하기 위한 XE 템플릿 구문을 사용합니다.

<!--@if(!$is_logged)--> 
   ① 로그인이 안되어 있을때 내용 (로그인 폼)
<!--@else-->
   ② 로그인이 되었을 때 보여줄 내용 (회원 정보 출력)
<!--@end-->

3# 로그인을 위한 폼(form)을 ①에 작성합니다.

<!--%import("filter/login.xml")-->
※ login.xml 문서를 불러온다.
<form action="./" method="post" onsubmit="return procFilter(this, login)" id="fo_login">
※ 폼을 만들고 전송하게 되면(onsubmit) procFilter() 함수를 실행한다.
<ul>※ 아이디와 비밀번로 입력칸을 만든다.
   <li><input name="user_id" type="text" /></li>
   <li><input name="password" type="password" /></li>
</ul>
<p class="keep">
   <input type="checkbox" name="keep_signed" value="Y" class="inputCheck" 
    onclick="if(this.checked) return confirm('{$lang->about_keep_signed}');"/><label>{$lang->keep_signed}</label>
	※ 로그인 유지에 체크하면 알림사항을 화면에 표시하고 확인도장을 받는다.
</p>
   <span><input type="submit" value="{$lang->cmd_login}" /></span>※ 로그인 버튼을 만든다.
</form>
※ 회원가입 등의 링크 리스트를 만든다. 특정 페이지에서 회원가입을 받으려면 'act' 앞에 'mid','페이지이름', 을 더해준다.
<ul>
   <li><a href="{getUrl('act','dispMemberSignUpForm')}"><span>{$lang->cmd_signup}</span></a></li>
   <li><a href="{getUrl('act','dispMemberFindAccount')}"><span>{$lang->cmd_find_member_account}</span></a></li>        
   <li><a href="{getUrl('act','dispMemberResendAuthMail')}">{$lang->cmd_resend_auth_mail}</a></li>
</ul>

4# 회원의 정보를 보여주기 위한 리스트를 ②에 작성합니다.

<!--%import("./filter/logout.xml")-->
※ logout.xml 문서를 불러온다.
<form action="" method="post">
※ action이 없는 빈폼을 만든다.
<div class="member_{$logged_info->member_srl}"><strong>{$logged_info->nick_name}</strong></div>
※ 회원의 닉네임을 클릭하면 팝업정보를 표시한다.
<a href="{getUrl('act','dispMemberLogout')}" class="button red"><span>{$lang->cmd_logout}</span></a>
※ 링크버튼을 클릭하면 로그아웃 한다.
<ul>
※ 반복문으로 $logged_info 변수의 배열을 나누어 담고 리스트로 만든다.
<!--@foreach($logged_info->menu_list as $key => $val)-->
<li><a href="{getUrl('act',$key,'member_srl','','page','')}">{Context::getLang($val)}</a></li>
<!--@end-->
※ 최고관리자이면 새창을 열어 관리자 모듈 페이지를 보여준다.
<!--@if($logged_info->is_admin=="Y" && !$site_module_info->site_srl)-->
<li><a href="{getUrl('','module','admin')}" onclick="window.open(this.href);return false;">{$lang->cmd_management}</a></li>
<!--@end-->
</ul>
※ 마지막 로그인 일자와 시간을 보여준다.
<p>{$lang->last_login}<br /><span>{zDate($logged_info->last_login, "Y-m-d H:i")}</span></p>
</form>

5# 로그인 아이디 입력칸에 포커스를 주려면 아래 스크립트를 레이아웃 맨 하단 또는 작성한 ① 위에 삽입합니다.

<script type="text/javascript">
    var keep_signed_msg = "{$lang->about_keep_signed}";
    xAddEventListener(window, "load", function(){ doFocusUserId("fo_login"); });
</script>

6# JS 문서에 로그인 영역 포커스 주는 doFocusUserId()와 로그인후 completeLogin() 추가 합니다.

/*로그인 영역에 포커스 */
function doFocusUserId(fo_id) {
    if(xScrollTop()) return;
    var fo_obj = xGetElementById(fo_id);
    if(fo_obj.user_id) {
        try{
            fo_obj.user_id.focus();
        } catch(e) {};
    }
}
/* 로그인 후 */
function completeLogin(ret_obj, response_tags, params, fo_obj) {
    var url =  current_url.setQuery('act','');
    location.href = url;
}

이제 로그인 위젯 없이도 로그인을 할 수 있게 되었습니다. 아이디 또는 비밀번호가 잘 못 입력되어도 에러 메시지를 보여 줍니다.


모달창을 이용한 로그인

모달창(Modal Window) 또는 모달 윈도우는 일반적으로 모달 대화상자라고 불리는데 우리가 자주 사용하는 파일 열기/저장 대화상자를 닮았기 때문입니다. 모달 창들은 사용자와 상호작용하는 것을 무척 좋아합니다. 웹에서 이미지를 크고 자세하게 보여주거나, 또는 긴급한 상황을 알리고 싶을 때도 모달 윈도우가 심부름을 하게 되지요. XE가 로그인 위젯을 사용하지 않는 경우 위와 같이 레이아웃에서 직접 로그인 영역을 만들고 사용할 수도 있지만, 가끔 모달창을 불러 심부름을 시키기도 합니다. 로그인 위젯이 괜히 심통을 부린것 같네요. XE 형이 모달창 로그인도 만들어 본답니다. 어떻게 만드는지 한번 따라가 볼까요?

image


Modal 1# header에 있는 로그인 링크 속성을 클릭했을때 모달레이어 보기로 변경합니다.

변경전 : <a href="{getUrl('mid','example_main','act','dispMemberLoginForm')}">{$lang->cmd_login}</a>
변경후 : <a href="#modalLogin" onclick="jQuery('#modalLogin').css('display','block');">로그인</a>
※ 로그인을 클릭하게 되면 #modalLogin 아이디를 가진 DIV를 보여줘!(display:block)

Modal 2# 레이아웃 맨 아래 전체를 감싸는 DIV 바깥으로 #modalLogin 아이디를 가진 DIV를 작성합니다.

<!--// 모달 로그인 시작  -->
<!--%import("filter/login.xml")-->
<div id="modalLogin" class="modalLogin">
   <span class="modalWindow"></span>
   <div id="loginLayer" class="loginLayer">
      <div class="modal_header">
         <p class="text_welcome">Welcome to {$layout_info->logo_image_alt} Website!</p>
         <ul class="help">
            <li><a href="{getUrl('act','dispMemberSignUpForm')}" class="button black"><span>{$lang->cmd_signup}</span></a></li>
            <li><a href="{getUrl('act','dispMemberFindAccount')}" class="button black"><span>{$lang->cmd_find_member_account}</span></a></li>
            <li><a href="{getUrl('act','dispMemberResendAuthMail')}" class="button black"><span>{$lang->cmd_resend_auth_mail}</span></a></li>
         </ul>
      </div>
   <button type="button" class="close" onclick="document.getElementById('modalLogin').style.display='none'" accesskey="X"><span>Close</span></button>
   <form action="" method="post" onsubmit="return procFilter(this, login)">
      <ul class="input_box">
         <li><input name="user_id" type="text" class="inputText" id="uid" /></li>
         <li><input name="password" type="password" class="inputText" id="upw" /></li>
      </ul>
      <p class="keep"><input name="keep_signed" type="checkbox" id="keepA" value="Y" class="inputCheck" onclick="if(this.checked) return confirm('{$lang->about_keep_signed}');"/><label for="keepA">로그인 유지</label></p>
      <div class="loginBtn">
         <p><span class="button blue large"><input type="submit" value="{$lang->cmd_login}" /></span><span class="button large"><input type="button" value="{$lang->cmd_back}" onclick="document.getElementById('modalLogin').style.display='none'" accesskey="X"></span></p>
      </div>
   </form>
   </div>
</div><!--//  modalLogin end -->
<!--// 모달 로그인 끝  -->

모달 윈도우에서는 창닫기 버튼이 추가 되고 아이디 부분에서 깜빡이는 포커싱을 위한 스크립트는 삭제합니다. 레이아웃 문서에 숨겨진 부분을 보여주는 것이기 때문에 불필요합니다.


Modal 3# 모달 윈도우를 위한 CSS 레이아웃을 작성합니다.

/* modalLogin 설정 */
.modalLogin {display:none; position:fixed; left:0; top:0; _position:absolute; width:100%; height:100%; z-index:100;} 
.modalLogin .modalWindow{ display:block; position:fixed; border:0; left:0; top:0; _position:absolute; width:100%; height:100%; background:#000; -moz-opacity:.50; filter:alpha(opacity=50); opacity:.50;}
.modalLogin .loginLayer{ position:absolute; width:440px; top:150px; left:50%; margin:0 0 0 -230px; border:10px solid #D6D6D6; background:#F2F2F2;}
.modalLogin .loginLayer .modal_header {height:130px; background:#151515 url(../images/modal_label.gif) no-repeat 20px 20px;}
.modalLogin .loginLayer .modal_header .text_welcome {position:absolute; top: 55px; left: 20px; color:#FFF;}
.modalLogin .loginLayer .modal_header .help {position:absolute; top: 85px; left: 20px; list-style:none; text-align:center;}
.modalLogin .loginLayer .modal_header .help li {float:left; display:inline; font-size:12px; padding-right:10px;}
.modalLogin .loginLayer form{display:block; *zoom:1;}
.modalLogin .loginLayer form:after{ content:""; display:block; clear:both;}
.modalLogin .loginLayer .input_box {list-style:none; background:url(../images/modal_username.gif) no-repeat 0 0; padding: 0 0 0 75px; margin:20px 0 0 20px;}
.modalLogin .loginLayer .inputText{ width:300px; height:25px; padding:0 0 0 10px; margin:0 0 10px 0; border:1px solid #ddd; font:16px Tahoma; color:#333; font-weight: bold;}
.modalLogin .loginLayer .inputText:focus{ background-color:#fbfbfb;}
.modalLogin .loginLayer .inputCheck{ margin:0 3px 0 0; width:13px; height:13px; vertical-align:middle;}
.modalLogin .loginLayer .keep{ margin:0 0 10px 96px; font-size:12px; line-height:normal; white-space:nowrap;}
.modalLogin .loginLayer .keep label{ color:#444; letter-spacing: -1px;}
.modalLogin .loginLayer .loginBtn {text-align:center; background: #E8E8E8; padding:10px 0;}
.modalLogin .loginLayer .loginBtn span {margin:0 20px;}
.modalLogin .loginLayer .close{ position:absolute; cursor:pointer; border:0; padding:0; top:0; right:0; width:50px; height:50px; background:url(../images/buttonCloseX.gif) no-repeat center center;}
.modalLogin .loginLayer .close span{ position:absolute; font-size:0; line-height:0; width:0; height:.; overflow:hidden; visibility:hidden;}

Modal 4# CSS 맨 위에 화면 전체를 덮을 수 있도록 height:100%; 를 추가합니다.

html, body {height:100%;}

사용된 이미지

모달 닫기 버튼 이미지      모달 라벨      모달 아이디배경

모달창은 CSS에서 display:block; 으로 숨겨두게 됩니다. 로그인 링크를 클릭했을때만 보이도록 하는 것입니다. 레이아웃 만들기 예제에서 모달창을 이용한 로그인을 확인해 보실 수 있습니다.