EOF
return
""
. $bar_search
. $bar_user
. $bar_menu
. "
"
# 여기 추가
. $gotobar_script
. "
\n"
;
}
}}}
[[/GotoBar개선]]에서 추가된 GetGotoForm에서, 각각의 요소에 이벤트 처리 부분을 추가해준다. 일일이 표시하기 힘들어서 함수를 다시 통채로 적음.
그리고 Goto매크로와 공유하는 함수라서, 이게 매크로로 쓰였는지 아닌지에 따라 다르게 출력할 부분들이 많다. (아예 goto매크로 쪽 구현을 다시 바꿔버릴 걸 그랬나 싶기도)
{{{#!vim perl
sub GetGotoForm {
my ($not_macro, $string);
if (@_) {
($string) = @_;
} else {
$not_macro = 1;
}
my $result;
my $location_prefix = $ScriptName . &ScriptLinkChar();
my $param_backup = $q->param("id");
$q->param("id", "$string");
$GotoTextFieldId++;
$result =
$q->start_form(
-name => ($not_macro?"goto_form":""),
-method => "POST",
-action => "$ScriptName",
-enctype => "application/x-www-form-urlencoded",
-accept_charset => "$HttpCharset",
-onSubmit =>
"document.location.href = "
. "'$location_prefix'+document.getElementById('goto_$GotoTextFieldId')"
. ".value.replace(/\\s*\$/,'').replace(/ /g,'_');"
. "return false;"
,
)
. "\n"
. &GetHiddenValue("action", "browse")
. "\n"
. $q->textfield(
-name => ($not_macro?"goto_text":""),
-id => "goto_$GotoTextFieldId",
-class => "goto",
-size => "30",
-value => "$string",
-accesskey => ($not_macro?"g":""),
-title => ($not_macro?T("Go")."(Alt + g)":""),
-tabindex => ($not_macro?"1000":""),
# IE&FF
-onKeyup=> ( $not_macro?
"getMsg('$ScriptName')"
:
""
),
# FF에서 처음에 한글로 입력을 시작할 때
# up,down 키로 목록과 필드를 오갈때
-onKeydown=> ( $not_macro?
"goto_text_keydown(this,event); "
. "getMsg('$ScriptName')"
:
""
),
)
. " "
. $q->submit(
-class => "goto",
-name => "Submit",
-value => T("Go"),
-tabindex => ($not_macro?"1002":""),
)
# 자동 완성 목록이 나올 DIV
. ($not_macro? "
\n"
. "\n"
. $q->popup_menu(
-name => "goto_select",
-size => "15",
-tabindex => "1001",
-onBlur => "goto_list_blur(this,true,true);_goto_field.select()",
-onChange => "goto_list_blur(this,true,false);",
-values => ["-- Loading page list... --"],
-onKeydown=> "return goto_list_keydown(this,event);",
)
. "
\n"
:
""
)
. $q->endform
;
$q->param("id", $param_backup);
return $result;
}
}}}
브라우저의 버그(?)를 편법으로 풀기 위해서, 검색 필드가 있는 폼에도 이름을 붙여 주어야 했다.
{{{#!vim perl
sub GetSearchForm {
...
$result =
# 인자로 이름을 적어 줌
&GetFormStart("search_form")
. &GetHiddenValue("dosearch", 1)
. $q->textfield(
-name => "search",
-class => "search",
# 하는 김에 size도 좀 늘렸음
-size => "30",
-accesskey => "s",
-title => "Alt + s",
)
...
}
}}}
=== # wikiscript.js 수정 ===
==== # 서버와의 통신을 위한 라이브러리 ====
이건 위에서 언급한 샘플 코드에 library로 들어 있던 파일의 내용을 그대로 가져왔다. 원 저자는 일본사람인 듯 하고 맘대로 쓰게 공개되어 있는 것 같음.
{{{#!vim javascript
// 바로 가기 필드 자동 완성
//==============================================================================
// SYSTEM : 잠정판 크로스 프라우저 Ajax용 라이브러리
// PROGRAM : XMLHttpRequest에 의한 송수신을 합니다
// FILE NAME : jslb_ajaxXXX.js
// CALL FROM : Ajax 클라이언트
// AUTHER : Toshirou Takahashi http://jsgt.org/mt/01/
// SUPPORT URL : http://jsgt.org/mt/archives/01/000409.html
// CREATE : 2005.6.26
// TEST-URL : 헤더 http://jsgt.org/ajax/ref/lib/test_head.htm
// TEST-URL : 인증 http://jsgt.org/mt/archives/01/000428.html
// TEST-URL : 비동기
// http://allabout.co.jp/career/javascript/closeup/CU20050615A/index.htm
// TEST-URL : SQL http://jsgt.org/mt/archives/01/000392.html
//------------------------------------------------------------------------------
// 최신 정보 : http://jsgt.org/mt/archives/01/000409.html
// 저작권 표시의무 없음. 상업 이용과 개조는 자유. 연락 필요 없음.
//
//
////
// 동작가능한 브라우저 판정
//
// @sample if(chkAjaBrowser()){ location.href='nonajax.htm' }
// @sample oj = new chkAjaBrowser();if(oj.bw.safari){ /* Safari 코드 */ }
// @return 라이브러리가 동작가능한 브라우저만 true true|false
//
// Enable list (v038현재)
// WinIE 5.5+
// Konqueror 3.3+
// AppleWebKit계(Safari,OmniWeb,Shiira) 124+
// Mozilla계(Firefox,Netscape,Galeon,Epiphany,K-Meleon,Sylera) 20011128+
// Opera 8+
//
function chkAjaBrowser()
{
var a,ua = navigator.userAgent;
this.bw= {
safari : ((a=ua.split('AppleWebKit/')[1])?a.split('(')[0]:0)>=124 ,
konqueror : ((a=ua.split('Konqueror/')[1])?a.split(';')[0]:0)>=3.3 ,
mozes : ((a=ua.split('Gecko/')[1])?a.split(" ")[0]:0) >= 20011128 ,
opera : (!!window.opera) && ((typeof XMLHttpRequest)=='function') ,
msie : (!!window.ActiveXObject)?(!!createHttpRequest()):false
}
return (this.bw.safari||this.bw.konqueror||this.bw.mozes||this.bw.opera||this.bw.msie)
}
////
// XMLHttpRequest 오브젝트 생성
//
// @sample oj = createHttpRequest()
// @return XMLHttpRequest 오브젝트(인스턴스)
//
function createHttpRequest()
{
if(window.ActiveXObject){
//Win e4,e5,e6용
try {
return new ActiveXObject("Msxml2.XMLHTTP") ;
} catch (e) {
try {
return new ActiveXObject("Microsoft.XMLHTTP") ;
} catch (e2) {
return null ;
}
}
} else if(window.XMLHttpRequest){
//Win Mac Linux m1,f1,o8 Mac s1 Linux k3용
return new XMLHttpRequest() ;
} else {
return null ;
}
}
////
// 송수신 함수
//
// @sample sendRequest(onloaded,'&prog=1','POST','./about2.php',true,true)
// @param callback 송수신시에 기동하는 함수 이름
// @param data 송신하는 데이터 (&이름1=값1&이름2=값2...)
// @param method "POST" 또는 "GET"
// @param url 요청하는 파일의 URL
// @param async 비동기라면 true 동기라면 false
// @param sload 수퍼 로드 true로 강제、생략또는 false는 기본
// @param user 인증 페이지용 사용자 이름
// @param password 인증 페이지용 암호
//
function sendRequest(callback,data,method,url,async,sload,user,password)
{
//XMLHttpRequest 오브젝트 생성
var oj = createHttpRequest();
if( oj == null ) return null;
//강제 로드의 설정
var sload = (!!sendRequest.arguments[5])?sload:false;
if(sload || method.toUpperCase() == 'GET')url += "?";
if(sload)url=url+"t="+(new Date()).getTime();
//브라우저 판정
var bwoj = new chkAjaBrowser();
var opera = bwoj.bw.opera;
var safari = bwoj.bw.safari;
var konqueror = bwoj.bw.konqueror;
var mozes = bwoj.bw.mozes ;
//송신 처리
//opera는 onreadystatechange에 중복 응답이 있을 수 있어 onload가 안전
//Moz,FireFox는 oj.readyState==3에서도 수신하므로 보통은 onload가 안전
//Win ie에서는 onload가 동작하지 않는다
//Konqueror은 onload가 불안정
//참고 http://jsgt.org/ajax/ref/test/response/responsetext/try1.php
if(opera || safari || mozes){
oj.onload = function () { callback(oj); }
} else {
oj.onreadystatechange =function ()
{
if ( oj.readyState == 4 ){
callback(oj);
}
}
}
//URL 인코딩
data = uriEncode(data)
if(method.toUpperCase() == 'GET') {
url += data
}
//open 메소드
oj.open(method,url,async,user,password);
//헤더 application/x-www-form-urlencoded 설정
setEncHeader(oj)
//디버그
//alert("////jslb_ajaxxx.js//// \n data:"+data+" \n method:"+method+" \n url:"+url+" \n async:"+async);
//send 메소드
oj.send(data);
//URI 인코딩 헤더 설정
function setEncHeader(oj){
//헤더 application/x-www-form-urlencoded 설정
// @see http://www.asahi-net.or.jp/~sd5a-ucd/rec-html401j/interact/forms.html#h-17.13.3
// @see #h-17.3
// ( enctype의 기본값은 "application/x-www-form-urlencoded")
// h-17.3에 의해、POST/GET 상관없이 설정
// POST에서 "multipart/form-data"을 설정할 필요가 있는 경우에는 커스터마이즈 해주세요.
//
// 이 메소드가 Win Opera8.0에서 에러가 나므로 분기(8.01은 OK)
var contentTypeUrlenc = 'application/x-www-form-urlencoded; charset=UTF-8';
if(!window.opera){
oj.setRequestHeader('Content-Type',contentTypeUrlenc);
} else {
if((typeof oj.setRequestHeader) == 'function')
oj.setRequestHeader('Content-Type',contentTypeUrlenc);
}
return oj
}
//URL 인코딩
function uriEncode(data){
if(data!=""){
//&와=로 일단 분해해서 encode
var encdata = '';
var datas = data.split('&');
for(i=1;i
==== # 위키에 적용하기 위한 코드 ====
이 패치의 목적을 달성하기 위해, 샘플 예제들을 읽어보고 거기 있는 것들을 레고 조립하듯 이리 저리 짜맞추고, 브라우저별로 반응이 다른 부분들을 손질하고, 필요한 부분은 추가해서 만든 코드 =.=; 뭔가 비효율적이다 싶은 곳들도 여러 군데 있을 것임.
이런 저런 전역변수들
{{{#!vim javascript
// 여기서부터는 UseModWiki ext버전에서 바로가기 필드 자동완성을 위해 수정했음
// 필요한 전역변수
var have_data = 0;
var page_list;
var previous_search = 'previous';
var resOj;
var timeout = 0;
var timeout_url;
var div_blur = 0;
var user_last_input;
// 엘리먼트들의 이름을 짧게 쓰기 위한 변수
var _goto_field;
var _select_field;
var _list_div;
var _search_field;
}}}
변수 초기화
{{{#!vim javascript
function gotobar_init() {
_goto_field = document.goto_form.goto_text;
_select_field = document.goto_form.goto_select;
_list_div = document.getElementById('goto_list');
_search_field = document.search_form.search;
}
}}}
처음 불리면 서버에 접속해서 Local:action=titleindex""를 받아오고, 두번째부터는 그냥 목록 갱신만 시킴
{{{#!vim javascript
//송수신 함수
function getMsg(url) {
// 0.2초 이내에는 다시 갱신하지 않음 - 타이핑 속도를 못 따라잡는 문제
if (timeout) {
return;
}
timeout=1
timeout_url=url
// setTimeout("timeout=0;",200)
setTimeout("timeout=0; getMsg(timeout_url);",300)
if (have_data) {
renew_select()
}
else {
// 처음 한번만 서버에서 목록을 받아옴
have_data = 1;
sendRequest(
on_loaded1, //콜백함수
'&action=titleindex', //파라메터
'GET', //HTTP메소드
url, //URL
true, //비동기
true //강제로드
)
}
}
}}}
서버에서 응답이 왔을 때 쓰이는 콜백함수
{{{#!vim javascript
function on_loaded1(oj)
{
//응답을 취득
var res = decodeURIComponent(oj.responseText)
// titleindex 출력을 받아서, 개별 페이지 이름의 배열로 분리
page_list = res.split(/\s+/)
// select 목록 갱신
renew_select()
}
}}}
후보 목록을 갱신하는 함수. 이런 저런 조건을 따져서 최대한 무의미한 (결과에 변화가 없는) 갱신을 하지 않게 하려 했음
{{{#!vim javascript
function renew_select() {
// 사용자가 입력한 값을 포함한 페이지 제목만 추려냄
var search = _goto_field.value;
// 입력값에 변동이 없다면 진행하지 않는다
if (previous_search == search || !page_list) {
return;
}
previous_search = search
// 목록에서 선택한 직후라면 진행하지 않는다
if (div_blur) {
div_blur = 0;
return;
}
// 뒤의 공백을 제거하고, 중간 공백은 "_"로 치환하고, 대소문자 구분 안함
var temp = search;
search = search.replace(/\s*$/, '').replace(' ','_');
// 입력값이 널 문자 또는 일정 길이 이하면 중단 - 속도 문제
if (search.length < 1) {
return false;
}
user_last_input = temp; // up키로 되돌아갔을때 복원하기 위한 값
search = new RegExp(search, "i")
var new_list = new Array();
for( i = 0 ; i < page_list.length ; i++ ){
if (page_list[i].match(search)) {
new_list.push(page_list[i])
}
}
// select 목록 갱신
_list_div.style.display='block'
resOj = new chgARRAYtoHTMLOptions(new_list,_select_field)
resOj.addOptions()
}
}}}
이건 좀 묘한 함수인데.. 샘플 소스에서는 XML파일을 인자로 받아서, 여러가지 동작을 할 수 있는 오브젝트를 반환하는 함수가 있었다. 근데 여기서는 굳이 오브젝트까지 쓸 필요는 없었지 싶음
{{{#!vim javascript
// 배열을 인자로 받아서, oj에 해당하는 select 목록을 조작하는 객체를 반환
// chgXMLtoHTMLOptions()의 흉내를 내어서 수정함
function chgARRAYtoHTMLOptions(arr,oj) {
return {
//XML의 items,value,text을 연결하여 배열로 반환합니다
setItems : function() {
return arr;
},
//XML의 데이터로부터 오브젝트를 생성합니다
addOptions : function() {
//모든 옵션을 지웁니다
this.delAllOptions(oj)
//XML 데이터의 오브젝트를 받아 냅니다
var data = this.setItems()
//"item" 태그가 나온 순서대로 처리합니다
for( i = 0 ; i < data.length ; i++ ) {
var text = data[i]
var value = data[i]
oj.options[oj.length]=new Option(text,value)
}
},
//index로 지정된 옵션을 지웁니다
delOptionByIndex : function(index) {
oj.options[index]=null
},
//모든 옵션을 지웁니다
delAllOptions : function(oj) {
var optionIndex = oj.options.length
for ( i=0 ; i <= optionIndex ; i++ ) {
oj.options[0]=null // 어째서 "i"가 아니라 "0"일까...?
}
},
//option이 선택된 때의 처리
onselectedOption : function(oj) {
_goto_field.value = oj.options[oj.selectedIndex].value
previous_search = _goto_field.value;
}
}
}
}}}
인자에 따라서, 목록 출력을 갱신하거나, 목록이 있는 DIV를 닫거나, 둘 다 수행하거나 하는 함수
{{{#!vim javascript
function goto_list_blur(oj, field_update, close_div) {
div_blur = 1 // 텍스트필드값이 변경되더라도 목록 갱신을 하지 않게 함
if (field_update) {
resOj.onselectedOption(oj)
}
if (close_div) {
_list_div.style.display = 'none'
}
}
}}}
목록이 출력되는 SELECT 박스 내에서 키가 눌렸을 때 불리는 함수
{{{#!vim javascript
function goto_list_keydown(oj, KeyStorke) {
var evt = KeyStorke || window.event;
var nKeyCode = evt.keyCode;
// 목록을 닫고 텍스트 필드로 되돌아갈 지 여부 판단
if (nKeyCode == 13 || nKeyCode == 32) {
// enter,space가 눌렸을 때 - 필드 갱신 후 닫음
goto_list_blur(oj, true, true);
_goto_field.focus();
return false;
}
else if (nKeyCode == 27 || (nKeyCode == 38 && oj.selectedIndex <= 0)) {
// esc가 눌렸거나
// up이 눌렸고 목록의 제일 위에 있었을 때 - 필드 갱신 없이 닫기만 함
goto_list_blur(oj, false, true);
_goto_field.focus();
_goto_field.value = user_last_input;
setTimeout("_search_field.focus(); _goto_field.focus(); _goto_field.value = user_last_input;", 20); // for IE
return false;
}
else if (nKeyCode == 8) {
// BS - 필드 값에서 한 글자 지우고 포커스 이동
user_last_input = _goto_field.value.substring(0,_goto_field.value.length-1);
_goto_field.focus();
_goto_field.value = user_last_input;
setTimeout("_search_field.focus(); _goto_field.focus(); _goto_field.value = user_last_input;", 20); // for IE
return true;
}
else {
return true;
}
}
}}}
사용자가 입력하는 텍스트 필드에서 키가 눌렸을 때 불리는 함수. 존재 이유는 딱 하나, 필드에서 down 커서키를 눌러서 목록으로 옮겨가기 위함 -_-;
{{{#!vim javascript
function goto_text_keydown(oj, KeyStorke) {
var evt = KeyStorke || window.event;
var nKeyCode = evt.keyCode;
if (nKeyCode == 40 && resOj) { // down
_list_div.style.display = 'block'
if (_select_field.options.length > 0) {
_search_field.focus() // 웹마 때문에 우회함
_select_field.focus()
}
}
else if (nKeyCode == 38) { // up
_list_div.style.display = 'none'
}
}
}}}
=== # 추가 업데이트 내역 ===
ext 2.25b - 바로가기폼에 공백이 여러번 포함된 단어를 적었을 때, 첫번째 공백만 언더스코어(_)로 바뀌는 문제 해결
=== # 사용자 의견 ===
지금... 페이지 목록 보여주는 건 다 됐는데, DIV 박스의 스타일 속성을 어떻게 줘야 되는지 몰라서 좀 흉하게 나옵니다. OTL 일단 지금까지 작업한 거 올려놓고 도움 요청을 해야겠네요.
-_-;;; 백스페이스, ESC등을 눌렀을 때 처리까지 추가하고 IE와 FF에서 제대로 되는 것도 확인했는데 왜 웹마에서 문제가 되냐 =.=
: [http://www.mdiwebma.com/webma/?doc=bbs/gnuboard.php&bo_table=bug&wr_id=849 웹마 버그 신고]
웹마에서 ESC가 동작하지 않는 문제 빼고는 그럭저럭 만족스럽게 돌아가고, 나머지 문제는 "해결되었거나, 내 힘으로 해결하기는 불가능하다고 판단됨"이므로 -_-; 일단 소스 정리해서 올렸습니다.
----
[[위키위키분류]]