이글루스에 추가된 기능을 참고하였음.
반대로 자기가 일부러 뒤로 가기를 했는데 저 창이 떠서 귀찮을 때도 있겠지만, 그런 귀찮음은 감수하도록 하자.
주인장이 자바스크립트를 잘 몰라서, 올바르게 사용한 것인지 확실치 않음. 잘 아는 분들이 아래 구현의 내용을 봐주었으면 함.
IE와 FF에서 자바스크립트를 처리하는 방식이 다른지, 구현에 문제가 좀 있었다. 다른 브라우저를 지원하기 위해서 별도의 수정이 필요할 지 모른다. 아래에 자세히 설명. (호환성문제(1))
[WebMa]에서 탭을 닫을 때는 동작을 안 한다. 웹마 쓰는 사람들 주의2.
// 작성 취소 시 확인 var previous_text = "", current_text = "", conflict = false, closeok = false; function chk_close(e, str) { if (!e) e = event; if (!closeok) { current_text = document.form_edit.text.value; if (conflict || (previous_text != current_text)) { e.returnValue = str; } } }
페이지 편집 모드(action=edit)거나 충돌이 발생했을 때 body에다가 "on before unload" 이벤트를 잡아내어 chk_close()함수를 부르도록 한다.
sub GetHtmlHeader { ... } } ### ############### ### 작성 취소시 확인 - 이 단락 추가 if ( (&GetParam("oldtime", "") ne "") || ((lc(&GetParam("action","")) eq "edit") && (&UserCanEdit($id,1))) ) { my $close_string = T('If you leave current page, the contents you are writing will not be stored.'); $bodyExtra .= qq( onbeforeunload="chk_close(event, '$close_string')" ); } ### 단축키 my $headExtra; if ($UseShortcut) { ... }
편집 폼에다가 submit시에는 경고창을 띄우지 않도록 closeok 변수를 true로 세팅하게 한다. 또한 편집 모드에 들어간 직후에 텍스트 에리어에 있는 내용을 미리 저장해둔다.
sub DoEdit { ... ### 편집모드에 들어갔을때 포커스가 편집창에 있도록 한다 # print &GetFormStart(); # print &GetFormStart("form_edit"); # 이 줄을 다시 아래와 같이 바꾼다 print $q->startform(-method=>"POST", -action=>"$ScriptName", -enctype=>"application/x-www-form-urlencoded", -name=>"form_edit", -onSubmit=>"closeok=true; return true;"); ### ... print "\n<script language=\"JavaScript\" type=\"text/javascript\">\n" . "<!--\n" . "previous_text = document.form_edit.text.value;\n" # 이 줄과 . (($isConflict)?"conflict = true;\n":"") # 이 줄 추가 . "document.form_edit.text.focus();\n" . "//-->\n" . "</script>\n"; ... }
그런데 편집 모드에서 상단의 "편집 도움말" 링크를 클릭했을 경우에도 경고창이 뜨는 문제가 있다. 그냥 새창으로 뜨는 링크는 문제가 없는 것 같은데, 편집 도움말의 경우는 자바스크립트를 사용해서 창을 만들어 띄우는 거라서 그런 듯 하다. 이걸 해결하기 위해서 도움말 관련 소스를 수정하여, 도움말 링크를 클릭했을 때도 closeok를 true로 세팅한다. (호환성문제(2): FF에서는 이 수정을 안 해도 도움말 띄울 때 경고창이 안 떴다)
sub HelpLink { my ($id, $text) = @_; my $url = "$ScriptName?action=help&index=$id"; ### 작성 취소 시 확인 # return "<a href=\"javascript:help('$url')\">$text</a>"; return "<a onclick=\"closeok=true;\" href=\"javascript:help('$url')\">$text</a>"; }
그런데 위처럼 수정을 하니, 이번엔 반대로 한 번 이상 도움말을 클릭한 이후에는 본문 편집 창에서도 경고 기능이 동작하지 않게 된다. -_-;;; 이걸 해결을 하기 위해서는 closeok를 다시 false로 되돌려 주어야 한다.
처음 시도한 방법은 위의 wikiscript.js에서 chk_close()의 제일 마지막 부분에 close = false; 를 넣는 것이었다. 그런데 이 방법은 IE에서만 통하고 FF에서는 통하지 않았다. (호환성문제(3)) -_-;;;;
다른 방법을 찾았는데, 도움말 창을 띄우는 help()를 찾아서 close=false;를 추가한다.
function help(s) { var w = window.open(s, "Help", "width=500,height=400, resizable=1, scrollbars=1"); closeok = false; w.focus(); }
여담으로, 도움말 링크에 onclick 이벤트를 넣지 않고, help(s)의 시작 부분에 closeok = true; 를 하여 경고창이 뜨지 않게 하는 방법을 써봤는데, unload 체크가 먼저 이뤄지는지 효과가 없었다.
If you leave current page, the contents you are writing will not be stored. 이 페이지를 벗어나면 작성중이던 글이 지워집니다.
이런 식이라면 또 다른 브라우저를 위해서는 새로운 곳을 수정해야 할 지도 모른다. 알려주면 반영하겠음.
textarea에서 onchage가 일어났는지 검사해서 일어났을 때만 메시지박스를 띄우는건 어떨까요? 그러면 뭔가 고쳤을 때만 물어볼 것 같은데에에...
그 생각도 했는데 (태터 최근 버전은 그러더군요), 그런데 이런 비교를 wiki.pl이 할 수 있는 게 아니라 자바 스크립트에서 처리해야 되는 거잖아요? chk_close()가 불리는 시점에 그런 스트링을 어떻게 넣을 수 있는지 알 수가 없어서요. 에디트 화면에 들어가는 순간 텍스트 박스의 내용을 자바스크립트 변수에 넣어 두고, chk_close() 내에서 다시 텍스트 박스의 내용을 읽어서 둘을 비교하여 달라진 게 있는지 검사한다...라는 건데 어떻게 해야 될지;;;
텍스트를 얻어내는 것은 preview 창 띄우는 부분을 참고했고, 비교는 그냥 != 를 써도 잘 되는군요. 수정한 거 올리겠습니다.
커헉, 첫 의견글에 "onchange"를 얼핏 봤을 때 그냥 변경이 일어났는지라는 의미로 생각했는데, 지금 확인하니 onChange 라는 이벤트가 따로 있군요. -.-;
onChange보다 텍스트 얻어내서 비교하는게 확실하니 결국 더 좋은 방법으로 구현하셨네요. :-)
네, onChange에서 또다른 변수 하나를 토글시키게 해 봤는데, 이건 사용자가 다른 곳을 클릭하거나 Tab을 눌러서 포커스를 이동해야 감지가 되더군요. 그냥 텍스트 고치다가 바로 뒤로 가면 안 되더라고요.