오늘 공부해보고 주변 사람들이 어려움을 겼는 한부분을 설명해보겠습니다.
이 부분을 이해하면 다음에 다른 코드들의 흐름을 읽어보고 따라가는데 도움이 될 것 입니다.
suggest.jsp
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.Collections"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%!
String[] keywords={
"AJAX",
"AJAX 실전 프로그래밍",
"자바",
"자바 프로그래밍",
"자바스터디",
"자바서비스",
"자바캔"
};
public List search(String keyword){
if(keyword==null || keywords.equals("")){
System.out.println("se");
return Collections.EMPTY_LIST;
}
System.out.println(keyword);
keyword=keyword.toUpperCase();
List result=new ArrayList(8);
for(int i=0;i<keywords.length;i++){
if(((String)keywords[i]).startsWith(keyword)){
result.add(keywords[i]);
}
}
return result;
}
%>
<%
request.setCharacterEncoding("utf-8");
String keyword=request.getParameter("keyword");
List keywordList=search(keyword);
out.print(keywordList.size());
out.print("|");
for(int i=0;i<keywordList.size();i++){
String key=(String)keywordList.get(i);
out.print(key);
if(i<keywordList.size()-1){
out.print(",");
}
}
%>
suggestclient.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="httpRequest.js">
</script>
<script type="text/javascript">
var checkFirst=false;
var lastKeyword="";
var loopSendKeyword=false;
function startSuggest(){
if(checkFirst==false){
setTimeout("sendKeyword();",500);
loopSendKeyword=true;
}
checkFirst=true;
}
function sendKeyword(){
if(loopSendKeyword==false)return;
var keyword=document.search.keyword.value;
if(keyword==''){
lastKeyword='';
hide('suggest');
}else if(keyword!=lastKeyword){
lastKeyword=keyword;
if(keyword!=''){
var params="keyword="+encodeURIComponent(keyword);
sendRequest("suggest.jsp",params,displayResult,'POST');
}else{
hide('suggest');
}
}
setTimeout("sendKeyword();",500)
}
function displayResult(){
if(httpRequest.readyState==4){
if(httpRequest.status==200){
var resultText=httpRequest.responseText;
var result=resultText.split('|');
var count=parseInt(result[0]);
var keywordList=null;
if(count>0){
keywordList=result[1].split(',');
var html='';
for(var i=0;i<keywordList.length;i++){
html+="<a href=\"javascript:select('"+keywordList[i]+"')\">"+keywordList[i]+"</a><br/>";
}
var listView=document.getElementById('suggestList');
listView.innerHTML=html;
show('suggest');
}else{
hide('suggest');
}
}else{
alert("에러발생:"+httpRequest.status);
}
}
}
function select(selectedKeyword){
document.search.keyword.value=selectedKeyword;
loopSendKeyword=false;
checkFirst=false;
hide('suggest');
}
function show(elementId){
var element=document.getElementById(elementId);
if(elementId){
element.style.display='';
}
}
function hide(elementId){
var element=document.getElementById(elementId);
if(elementId){
element.style.display='none';
}
}
</script>
<style>
#view{
border:1px solid #999;
}
</style>
</head>
<body>
<form name="search">
<input type="text" name="keyword" id="keyword" onkeydown="startSuggest()"/>
<input type="button" value="검색"/>
<div id="suggest" style="display:;position:absolute;left:0px;top:30px;">
<div id="suggestList"></div>
</div>
</form>
</body>
</html>
httpRequest.js
/**
*
*/
function getXMLHttpRequest(){
if(window.ActiveXObject){
try{
return new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
return new ActiveXObject("Microsoft.XMLHTTP");
}catch(el){
return null;
}
}
}else if(window.XMLHttpRequest){
return new XMLHttpRequest();
}else{
return null;
}
}
var httpRequest=null;
function sendRequest(url,params,callback,method){
httpRequest=getXMLHttpRequest();
var httpMethod=method?method:'GET';
if(httpMethod!='GET'&&httpMethod!='POST'){
httpMethod='GET';
}
var httpParams=(params==null||params=='')?null:params;
var httpUrl=url;
;
if(httpMethod=='GET'&&httpMethod!=null){
httpUrl=httpUrl+"?"+httpParams;
}
httpRequest.open(httpMethod,httpUrl,true);
httpRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
httpRequest.onreadystatechange=callback;
httpRequest.send(httpMethod=='POST'?httpParams:null);
}
여기까지가 내가 사용할 전체 코드이다. 이제 코드를 하나씩 실제로 사용되는 순서로 해설해 보겟습니다.
<body>
<form name="search">
<input type="text" name="keyword" id="keyword" onkeydown="startSuggest()"/>
<input type="button" value="검색"/>
<div id="suggest" style="display:;position:absolute;left:0px;top:30px;">
<div id="suggestList"></div>
</div>
</form>
</body>
여기서 보면 입력하는 부분(input태그) 과 버튼(button태그)가 있습니다.
그리고 그밑에 검색어 자동완성 목록을 넣어줄 수 있게 설계한 div태그가 있습니다.
그럼 우선 우리가 글자를 입력하게 되면 keydown이 되어서 onkeydown에 열결되어있는 startSuggest()함수가 실행됩니다.
var checkFirst=false;
var lastKeyword="";
var loopSendKeyword=false;
function startSuggest(){
if(checkFirst==false){
setTimeout("sendKeyword();",500);
loopSendKeyword=true;
}
checkFirst=true;
}
여기보시면 기본 값으로 checkFirst,loopSendKeyword가 false lastkeyword가 ""(비어있다는 뜻) 이렇게 배정되어있습니다.
startSuggest()함수가 keydown이라는 이벤트(행위) 발생으로 실행이 됩니다.
우선 if(checkFirst==false) 여기서 checkFirst가 false인지 확인을 하고 현재 초기값이 false인 그대로 이므로 checkFirst==false는 true가 되어서 if문에 진입하게 됩니다.
setTimeout("sendKeyword();",500);여기서 setTimeout은 두번째로 들어온 시간(1000=1초 현재 500이므로 0.5초)만큼 기다린 후에 실행하게 됩니다.
그동안 다음 코드를 실행하게 됩니다.
다음 코드로 따라가다가 loopSendKeyword=true;이걸 만나서 loopSendKeyword값을 true로 바꺼 줍니다.
또 밑으로 내려오면서 if문을 벗어나고 이어서 실행하다가 checkFirst=true; 만나서 checkFirst를true로 바꺼줍니다.
그러면 현재 startSuggest()함수를 모두 실행했습니다. setTimeout("sendKeyword();",500); 이코드를 실행하고 0.5초가 지나기 전까지는 실행되는 코드가 없어서 그냥 시간이 흘러가게 됩니다.
그리고 0.5초가 지나게 되면 sendKeyword()라는 함수를 실행하게 됩니다.
function sendKeyword(){
if(loopSendKeyword==false)return;
var keyword=document.search.keyword.value;
if(keyword==''){
lastKeyword='';
hide('suggest');
}else if(keyword!=lastKeyword){
lastKeyword=keyword;
if(keyword!=''){
var params="keyword="+encodeURIComponent(keyword);
sendRequest("suggest.jsp",params,displayResult,'POST');
}else{
hide('suggest');
}
}
setTimeout("sendKeyword();",500)
}
처음 시작해서 if(loopSendKeyword==false)return; 여기를 실행시키면 loopSendKeyword를 실행시키면
startSuggest함수에서 loopSendKeyword=true;로 true로 바꺼주어서 loopSendKeyword==false는 false(loopSendKeyword의 값이 false라는 것이아니고 조건이 false라는 말입니다.)가 되게 됩니다.
var keyword=document.search.keyword.value;를 실행하게 되면 keyword라는 변수에 document 즉 html태그들을 객체로 만들어서 저장시킨 집합(모음) 안에서 name이 search인 요소를 찾고 또 그 객체 안에서 keyword를 찾고 그 keyword의 값 (즉 안에 저장되어있는 내용)을 keyword에 저장하게 됩니다.
현재 코드에서는
search는 form태그를 가르키고(<form name="search">)
keyword는 form태그 내부에 있는 input 태그를 가르키게 됩니다.(<input type="text" name="keyword" id="keyword" onkeydown="startSuggest()"/>)
value 는 결국 우리가 입력한 값이 되게 됩니다.
즉 keyword라는 변수에 우리가 입력한 변수를 저장하게 됩니다.
그럼 우리가 자바 라고 입력했다고 가정하고 하겠습니다.
실행하고 밑으로 내려가서 if(keyword=='')를 만나면 우리는 keyword가 현재 자바 이기때문에 keyword==''는 false가되고
실행 하지 않고elseif로 넘어가게 됩니다. 그런데 만약 우리가 작성하고 지웠다고 하면 keyword가 ''가 되기 때문에 true가 되고 if문을 실행하게 됩니다. 그럼 if문이 어떤내용으로 실행되는지 확인해보겠습니다.
<--if문 내부(설명을 위한것 지금 자바를 입력했다고 가정하면 실행되지 않음)-->
lastKeyword='';를 만나서 lastKeyword에 ''를 저장해주게 됩니다.
그리고 hide('suggest');를 만나서 hide 함수를 실행 시켜주게 됩니다.
function hide(elementId){
var element=document.getElementById(elementId);
if(elementId){
element.style.display='none';
}
}
hide 함수를 보면 아까 hide('suggest');이렇게 실행했기 때문에 elementId='suggest'가 됩니다.
그럼 var element=document.getElementById(elementId); 여기를 만나면 아까 설명했던 document즉 html태그들을 객체로 만들어서 저장한 집합안에서 Id속성 값이 elementId인 객체를 찾게 됩니다.(getElementById ) 여기서 elementId는 suggest이므로 <div id="suggest" style="display:;position:absolute;left:0px;top:30px;"> 이게 element가 됩니다.
if(elementId) 이것을 만나면 elelmentId가 값을 가지고 있냐고 묻는 것이기 때문에 true가 됩니다. 저런게 조건문 작성시 0 null undefined '' 이거빼고는 다 true가 됩니다.
element.style.display='none';을 만나면 아까 찾았던
<div id="suggest" style="display:;position:absolute;left:0px;top:30px;"> 여기 안에 style( style="display:;position:absolute;left:0px;top:30px;") 여기 안에 display(display:;)를 찾아서 안에 값을 none으로 바꺼줍니다. 그러면 display:none;이 되고 우리 눈에 보이지 않게 됩니다.
그러고 나면 hide('suggest')함수가 끝나고 다시 sendKeyword()함수로 돌아오게 됩니다.
<--if문끝(이부분까지 자바라고 입력했다고 가졍했기때문에 현재 실행되지 않음)-->
이제 다시 보면 else if(keyword!=lastKeyword)를 만나고 초기에 var lastKeyword="";이렇게 lastKeyword를 ""로 정의 했고 현재 keyword는 자바 이므로 서로 같지 않습니다 그래서 현재 keyword!=lastKeyword는 true를 반환하게 됩니다.(만약 !=이 아니고 ==이였다면 false를 반환하고 else if문 무시됨)
var params="keyword="+encodeURIComponent(keyword); 이 문장을 만나면
keyword=(변수 keyword아님)이라는 글자에다가 변수 keyword 내용을 URIComponent 형식으로 바꺼서 keyword=와 더하게 됩니다. 즉 문자 문자 더하기는 두문자를 이어주는게 되기때문에 params는 keyword=형식이 변경된keyword 값이 됩니다.
sendRequest("suggest.jsp",params,displayResult,'POST'); 만나서 sendRequest 함수를 실행하고 4가지 인자를 같이 전달해 줍니다.
function sendRequest(url,params,callback,method){
httpRequest=getXMLHttpRequest();
var httpMethod=method?method:'GET';
if(httpMethod!='GET'&&httpMethod!='POST'){
httpMethod='GET';
}
var httpParams=(params==null||params=='')?null:params;
var httpUrl=url;
;
if(httpMethod=='GET'&&httpMethod!=null){
httpUrl=httpUrl+"?"+httpParams;
}
httpRequest.open(httpMethod,httpUrl,true);
httpRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
httpRequest.onreadystatechange=callback;
httpRequest.send(httpMethod=='POST'?httpParams:null);
}
httpRequest=getXMLHttpRequest(); 우선 여기를 실행하면
function getXMLHttpRequest(){
if(window.ActiveXObject){
try{
return new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
return new ActiveXObject("Microsoft.XMLHTTP");
}catch(el){
return null;
}
}
}else if(window.XMLHttpRequest){
return new XMLHttpRequest();
}else{
return null;
}
}
이 함수가 실행되고 window.ActiveXObject가 있으면 if(window.ActiveXObject)여기서 true가 반환되고
return new ActiveXObject("Msxml2.XMLHTTP");이것이 실행되면서 new ActiveXObject("Msxml2.XMLHTTP");이 객체가 반환 되는데 오류가 생기면 catch 로넘어가서return new ActiveXObject("Microsoft.XMLHTTP"); ActiveXObject("Microsoft.XMLHTTP");객체가 반환되고 여기서 또 오류가 생기면 return null; null을 반환하게 됩니다.
window.ActiveXObject이 없으면else if(window.XMLHttpRequest)로 넘어가서 window.XMLHttpRequest가 있는지 확인하고 있으면 return new XMLHttpRequest(); XMLHttpRequest 객체를 반환 해줍니다
그런데 이것도 없으면 return null null을 반환 합니다.
이렇게 다 실행하고 나서 sendRequest로 돌아오면 httpRequest에 xml관련 객체가 반환 되어 있을 것입니다.
var httpMethod=method?method:'GET';이것을 만나면 method?method:'GET'; method가 있으면method 없음면 'GET' 을 반환시키는 삼항연산자를 실행하게 됩니다. 현재 sendRequest("suggest.jsp",params,displayResult,'POST');여기서 method에 POST를 저장했으므로 POST가 반환되고 httpMethod에는 POST가 저장 됩니다.
if(httpMethod!='GET'&&httpMethod!='POST')를 만나서 httpMethod가 GET도 아니고 POST가 아니면 true를 반환하게 되고 현재 POST이므로 false를 반환하게 됩니다.(만약 true를 반환하게 된다면 httpMethod='GET';를 실행해서 httpMethod는 GET이 됩니다.)
var httpParams=(params==null||params=='')?null:params;여기를 실행하면 아까랑 똑같이 삼항연산자 인데params==null||params=='' 아까
var params="keyword="+encodeURIComponent(keyword);
sendRequest("suggest.jsp",params,displayResult,'POST');
이두코드로 인해서 parms에 keyword=형식이 변경된keyword 값이 저장 되었습니다. 빈공간도 아니고 null도 아니므로 false를 반환하고 httpParams에는 params의 값을 저장하게 됩니다.
var httpUrl=url; httpUrl은 sendRequest("suggest.jsp",params,displayResult,'POST');여기서 받아온 suggest.jsp를 httpUrl에 저장하게 됩니다.
if(httpMethod=='GET'&&httpMethod!=null) httpMethod는 var httpMethod=method?method:'GET';여기서 넘어온 POST로 결정 되었기 때무누에 false를 반환하고 그냥 지나가게 됩니다.(만약 true라면 httpMethod='GET';이것을 만나서httpMethod를 GET로 설정합니다.
httpRequest.open(httpMethod,httpUrl,true); 여기서 open에 각각 변수의 내용을 담아서 실행하고 첫번재 인자는 post인지 get인지 정하게 되고 두번째는 전송할 주소 세번째는 true이면 비동기 false이면 동기로 전송합니다.
httpRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); 헤더에 이러한 내용을 담고
httpRequest.onreadystatechange=callback; 상태가 변경될시 실행할 함수를 등록 현재 sendRequest("suggest.jsp",params,displayResult,'POST');여기서 displayResult를 받아왔으므로 displayResult가 등록됩니다.
httpRequest.send(httpMethod=='POST'?httpParams:null);여기서httpMethod=='POST'가 sendRequest("suggest.jsp",params,displayResult,'POST');여기서 POST받아와서 true가 됬으므로 httpParams을 넘겨 주게 된다.var httpParams=(params==null||params=='')?null:params;즉 여기서 설정된keyword=형식이 변경된keyword 값이전달 됩니다.
오늘은 여기서 마치고 내일 이어서 설명하겠습니다.