검색해봤지만 없는 것 같아 올립니다. 중복이면 지우겠습니다.
그리고 굉장히 쉬운 팁일 수도 있겠으나 저처럼 초보라서 어딜 건드려야 하는지 몰라 답답하실 분들께 도움이 되면 좋겠네요.


확장변수, 특히 여러줄입력칸(textarea) 사용시 태그가 먹히도록 하고 싶으시면
스킨파일의 extra_var_value.html를 수정합니다.(예를들어 zbxe/modules/board/skins/xe_board/extra_var_value.html)

<!-- textarea -->
<!--@elseif($val->type!--@elseif($val->type == 'textarea')-->
{nl2br(htmlspecialchars($val->value))}
&nbsp;


이 부분을 찾아서
{nl2br(htmlspecialchars($val->value))} 를 {$val->value} 로 바꿔주시면 됩니다.

줄바꿈(br) 태그만은 자동으로 먹히게 하고 싶다면 {nl2br($val->value)} 로 수정하면 되지요.
by Anna 안나 2008. 6. 1. 20:41
이틀째, 제로보드 XE와 씨름을 하고 있습니다.

메뉴 고정 펼침 기능이 체크만으로는 잘 안먹죠?

view plaincopy to clipboardprint? <!-- main_menu 3차 시작 --> <!--@if($val['list'])--> <ul style="display:block;"> <!--@foreach($val['list'] as $k => $v)--><!--@if($v['text'])--> <li <!--@if($v['selected'])-->class="on"<!--@end-->><a href="{$v['href']}" <!--@if($v['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$v['text']}</a></li> <!--@end--><!--@end--> <!-- main_menu 3차 시작 --> <!--@if($val['list'])--> <ul style="display:block;"> <!--@foreach($val['list'] as $k => $v)--><!--@if($v['text'])--> <li <!--@if($v['selected'])-->class="on"<!--@end-->><a href="{$v['href']}" <!--@if($v['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$v['text']}</a></li> <!--@end--><!--@end-->
3차 메뉴를 모두 펼치고 싶은 분들은, 레이아웃의
<ul style="display:block;"> 태그에 스타일을 추가해서 항상 보이도록 강제 세팅하시면 됩니다.

이 방법이야말로 언발에 오줌누기라서...

tree_menu.js 파일에 관해 빵조각(?)이 떨어져 있는데...

빵조각을 따라가기엔 시간이 촉박하여 저 방법을 썼습니다.

참고만하세요...
by Anna 안나 2008. 6. 1. 20:40
안녕하세요 럭키입니디 ㅏ.. #_#;;

많은분들이 메뉴와 관련된부분을 어려워 하시는거 같습니다.

1차메뉴부터..
<!-- main_menu 1차 시작 -->
<!--@foreach($main_menu->list as $key => $val)-->
<!--@if($val['text'])--> ①
<!--@if($val['selected'])--> ②
{@ $menu_1st = $val }
<!--@end--> ②
// 밑에 li안에있는 IF가 ③ <li <!--@if($val['selected'])-->class="on"<!--@end-->><a href="{$val['href']}" <!--@if($val['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$val['text']}</a></li> <!--@end--> ③
<!--@end--> ①
<!-- main_menu 1차 끝 -->
아닐수도있지만 전 제나름대로의 방식대로 이해했습니다. .....

일단 제나름대로 해석해보면..
메뉴정보를 가져와서, $val에 가져오고
①IF 로 $val['text'] 1차메뉴가 하나이상 있을때 밑에부분을 실행하란 말입니다
((-------IMAGE-------))
이안에서 또 ② If로 $val['selected'] 현재 메뉴가 선택되어있을때(만약 공지게시판에 접속했다면 공지게시판이 선택)
$menu_1st 에 $val값을 대입, ② End문으로 ② IF를 닫습니다.
그리고
<li <!--@if($val['selected'])-->class="on"<!--@end-->><a href="{$val['href']}" <!--@if($val['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$val['text']}</a></li>

CSS에서 지정해놓았던 <li 에 ③ IF $val['selected'] 메뉴가 선택되어있다면 class="on" 이란 클래스를 지정하고 End
a href .. 링크는 메뉴관리에서 설정한 링크를 지정하고, 그뒷부분은 메뉴관리에서 새창열기가 체크?을경우 새창으로 띄워줍니다
{$val['text']) 는 메뉴이름을 보여줍니다.
그리고 맨밑에 ① IF를 닫습니다.
1차 메뉴 끝
즉 1차메뉴가 한개이상 있을경우, <li><a href="링크">메뉴항목</a></li>
이렇게 반복적으로 출력한단 말이고, 현재 메뉴일경우 class="on"이란 클래스를 지정해줌으로써
현재 위치한 메뉴에 CSS를이용하여 효과를 주는것입니다.

----------------------------
<!-- 왼쪽 2차 메뉴 -->
<!--@if($menu_1st)-->
<ol id="lnb">
{@ $idx = 1 }
<!--@foreach($menu_1st['list'] as $key => $val)--><!--@if($val['text'])-->
<li <!--@if($val['selected'])-->class="on"<!--@end-->><a href="{$val['href']}" <!--@if($val['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$val['text']}</a> <!-- main_menu 3차 시작 -->
<!--@if($val['list'])-->
<ul>
<!--@foreach($val['list'] as $k => $v)--><!--@if($v['text'])-->
<li <!--@if($v['selected'])-->class="on"<!--@end-->><a href="{$v['href']}" <!--@if($v['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$v['text']}</a></li>
<!--@end--><!--@end-->
</ul>
<!--@end-->
</li>
{@$idx++}
<!--@end--><!--@end-->
</ol>
<!--@end-->
2차메뉴까지만 이해한다면 3차부터는 그대로 응용하시면 가능한 문제입니다.
일단 2차메뉴는 1차메뉴의 하위메뉴입니다.
그러므로 ① IF에서 1차메뉴가 있을? 밑에 문법을 실행합니다.
$idx에 1을 대입하고, $menu_1st , $key 메뉴정보를 $val에 가져옵니다.
여기서 보니 아마 $key는 2차메뉴정보가 있나봅니다.
② If로 val['text'] 2차메뉴가 있을때, 밑에 문법들을 실행하라..이말이죠
아까 1차메뉴와 똑같이, 메뉴가 선택되었을때 class="on" 을 지정하고,
링크나 새창 , 메뉴출력 .. 다 1차와 똑같이 되어있죠~
즉.. 무슨말이냐

저거 진하게 강조한부분만 변경하시면, 4차메뉴나 5차메뉴도 가져오실수있습니다.
음.. 그럼 ZBXE공식사이트에있는걸 기준으로 4차메뉴 추가한 예제를 보여드릴게요

<!-- main_menu 2차 시작 -->
<!--@if($menu_1st)-->
<ol id="lnb">
{@ $idx = 1 }
<!--@foreach($menu_1st['list'] as $key => $val)--><!--@if($val['text'])-->
<li <!--@if($val['selected'])-->class="on"<!--@end-->><a href="{$val['href']}" <!--@if($val['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$val['text']}</a> <!-- main_menu 3차 시작 -->
<!--@if($val['list'])-->
<ul>
<!--@foreach($val['list'] as $k => $v)--><!--@if($v['text'])-->
<li <!--@if($v['selected'])-->class="on"<!--@end-->><a href="{$v['href']}" <!--@if($v['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$v['text']}</a></li>
<!-- main_menu 4차 시작 -->
<!--@if($v['list'])-->
<ul>
<!--@foreach($v['list'] as $k => $v4)--><!--@if($v4['text'])-->
<li <!--@if($v4['selected'])-->class="laa"<!--@end-->><a href="{$v4['href']}" <!--@if($v4['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$v4['text']}</a></li>
<!--@end--> <!--@end--> <!--@end--> <!--@end-->
</ul>
<!--@end--><!--@end-->
</li>
{@$idx++}
<!--@end--><!--@end-->
</ol>
<!--@end-->
보시면 아시겠지만 3차메뉴에서는 2차메뉴인 val['list'] 에서 가져온것을 $v에 담아두고있습니다.
4차에서는 이걸이용해 3차메뉴인 $v['list'] 에서 가져온것을 $v4에 담아두고 이용하면 잘됩니다.
만약 5차메뉴도 추가하고싶다면 4차메뉴인 $v4['list'] 에서 가져와서 이용하시면 되겠죠..??

.......
쓰고보니까 글도 너무 복잡하고 길어서 죄송합니다 .ㅜ __ㅜ
모르거나 이해안가시는것은 댓글이나 쪽지로 주세요 __ ....

★ 제가 위에서 소스해석한게 틀릴수도있습니다. 하지만 무작정 붙여넣어서 쓰는것보단 이렇게라도 이해하고 쓰면 쉽게 할수있습니다.
by Anna 안나 2008. 6. 1. 20:39
((-------IMAGE-------))

이 팁은 메뉴를 플래시로 바꾼다고 해서 플래시를 배경으로 하고 그위에 메뉴가 자동으로 나타나게 하는 것이 아니라 ,
플래시를 만들때 메뉴를 직접 넣어서 만들어야 합니다.
실력이 미천하여 플래시를 배경으로 하고 그위에 메뉴가 구현되게 하기는 역부족입니다.

먼저 플래시파일을 제작해야겠죠(Flash Mx 나 Swish Max 사용)
제작된 플래시파일을 자신이 선택한 폴더에 업로드합니다.(Ex : /img/flash.swf)

자신이 사용중인 레이아웃 (Ex : xe_official)
1. layout.html를 에디터기로 엽니다.
[변경전] - 23줄부터
<div id="bodyWrap">
<div id="header">
<h1><a href="{$layout_info->index_url}"><!--@if(!$layout_info->logo_image)--><img src="./images/{$layout_info->colorset}/zeroBoardXE.png" alt="ZeroBoard™ XE" class="iePngFix" /><!--@else--><img src="{$layout_info->logo_image}" alt="logo" border="0" class="iePngFix" /><!--@end--></a></h1>[변경전] - 36줄부터
<!--GNB-->
<ul id="gnb">
<!-- main_menu 1차 시작 -->
<!--@foreach($main_menu->list as $key => $val)--><!--@if($val['link'])-->
<!--@if($val['selected'])-->
{@ $menu_1st = $val }
<!--@end-->

<li <!--@if($val['selected'])-->class="on"<!--@end-->><a href="{$val['href']}" <!--@if($val['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>{$val['link']}</a></li>

<!--@end--><!--@end-->
<!-- main_menu 1차 끝 -->
</ul>
<!--//GNB-->
[변경후] - 빨간색 부분 추가 (플래시메뉴 추가하는 소스)
<div id="header">
<h1><a href="{$layout_info->index_url}"><!--@if(!$layout_info->logo_image)--><img src="./images/{$layout_info->colorset}/zeroBoardXE.png" alt="ZeroBoard™ XE" class="iePngFix" /><!--@else--><img src="{$layout_info->logo_image}" alt="logo" border="0" class="iePngFix" /><!--@end--></a></h1>

<h2><script type="text/javascript">displayMultimedia("/img/flash.swf", "980","100",false);</script></h2>"980","100", "가로크기", "세로크기", 자신의 스킨에 맞게 변경하세요
[변경후] - 녹색 부분 제거 (기존의 메뉴부분 삭제, 다 지우면 왼쪽 2차메뉴 생성이 안됩니다)
<!--GNB-->
<ul id="gnb">
<!-- main_menu 1차 시작 -->
<!--@foreach($main_menu->list as $key => $val)--><!--@if($val['text'])-->
<!--@if($val['selected'])-->
{@ $menu_1st = $val }
<!--@end-->

<!--@end--><!--@end-->
<!-- main_menu 1차 끝 -->
</ul>
<!--//GNB-->여기까지가 layout.html를 편집하는 부분입니다.

2. 해당 칼라의 css를 엽니다. (Ex : default.css)
15줄
#header h1 { position:absolute; top:32px; left:25px;}
아래에
#header h2 { position:absolute; top:75px; right:0px;}
를 추가해 줍니다.
top:75px; right:0px; 도 자신의 스킨에 맞게 변경하세요.

이상 이렇게 하면 메뉴가 플래시로 바뀝니다.
바꾸기전에 자신의 메뉴가 확립된 상태에서 하는 것이 좋을 것입니다.
아니면 메뉴가 바뀔때마다 플래시메뉴를 편집해야 합니다.
별 것도 아니지만 혹시나 필요한 분이 있을까봐 올려봅니다.
by Anna 안나 2008. 6. 1. 20:37
((-------IMAGE-------))


제로보드4로 운영하던 사이트에서 사용하던 플래시 메뉴를
제로보드XE에 적용시켜 봤습니다.

제로보드XE에서 플래시 파일을 불러들이는 방식이 embed 태그없이 아주 간편하게 되어 있어서
오히려 적용하기기 수월해졌습니다.

제로보드4에서 사용할 때는 한 플래시 파일에 메뉴 버튼을 필요만큼 미리 만들어서 사용했었는데
한 플래시 파일에 한 버튼만 두고, 레이아웃의 메뉴 불러들이는 방식으로 플래시 파일을 삽입하는 방식으로 적용했습니다.

우선 레이아웃에서 플래시 파일을 읽어들이는 방식은
<script type="text/javascript">displayMultimedia("http://주소/submenulist.swf", "150","200",false);</script>
이와 같이 불러 들일 수 있지요

이 플래시 파일에 변수를 전달하려면
url 부분을 아래와 같이 확장하면 되더군요..
http://주소/submenulist.swf?변수1=값1&변수2=값2&변수3=값3.....
메뉴의 갯수가 고정적이라면 첨부한 submentlist.fla를 수정하여 위와 같은 방식으로 사용하면 될것입니다.

이제 submenu1.swf를 이용하여 레이아웃의 sub 메뉴에 적용시키는 방법을 말씀드리겠습니다.

레이아웃의 서브 메뉴 부분을 보면
<!-- 왼쪽 2차 메뉴 -->
<img src="./images/blank.gif" alt="" class="mask" />
<!--@if($menu_1st)-->
<ol id="lnb">
{@ $idx = 1 }
<!--@foreach($menu_1st['list'] as $key => $val)-->
<!--@if($val['text'])-->
<li <!--@if($val['selected'])-->class="on"<!--@end-->>
<a href="{$val['href']}" <!--@if($val['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>
{$val['text']}</a>
<!-- main_menu 3차 시작 -->
<!--@if($val['list'])-->
<ul>
<!--@foreach($val['list'] as $k => $v)-->
<!--@if($v['text'])-->
<li <!--@if($v['selected'])-->class="on"<!--@end-->>
<a href="{$v['href']}" <!--@if($v['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>
{$v['text']}</a>
</li>
<!--@end-->
<!--@end-->
</ul>
<!--@end-->
</li>
{@$idx++}
<!--@end-->
<!--@end-->
</ol>
<!--@end-->

이것을 아래와 같이 수정합니다.
<!-- 왼쪽 2차 플래시 메뉴 -->
<img src="./images/blank.gif" alt="" class="mask" />
<!--@if($menu_1st)-->
<ol id="lnb">
{@ $idx = 1 }
{@ $selbtnno = 0 }
{@ $selbtn3no = 0 }
<!--@foreach($menu_1st['list'] as $key => $val)--><!--@if($val['text'])-->
<!--@if($val['selected'])-->
{@ $selbtnno = 1 }
<!--@else-->
{@ $selbtnno = 0 }
<!--@end-->
<li>
<script type="text/javascript">displayMultimedia("http://주소/submenu1.swf?pselbtn={$selbtnno}&pbtn1menu={$val['text']}&pbtn1url={$val['href']}", "190","21",false);</script>
<!-- main_menu 3차 시작 -->
<!--@if($val['list'])-->
<ul <!--@if($val['selected'])-->style="display:block"<!--@end-->>
<!--@foreach($val['list'] as $k => $v)--><!--@if($v['text'])-->
<!--@if($v['selected'])-->
{@ $selbtn3no = 1 }
<!--@else-->
{@ $selbtn3no = 0 }
<!--@end-->
<li>
<script type="text/javascript">displayMultimedia("http://주소/submenu1.swf?pselbtn={$selbtn3no}&pbtn1menu={$v['text']}&pbtn1url={$v['href']}", "190","21",false);</script>
</li>
<!--@end--><!--@end-->
</ul>
<!--@end-->
</li>
{@$idx++}
<!--@end--><!--@end-->
</ol>
<!--@end-->



변경된 부분을 비교해 보면
2차 메뉴에서
<li <!--@if($val['selected'])-->class="on"<!--@end-->>
<a href="{$val['href']}" <!--@if($val['open_window']=='Y')-->onclick="window.open(this.href);return false;"<!--@end-->>
{$val['text']}</a>
이 부분을
<li>
<script type="text/javascript">displayMultimedia("http://주소/submenu1.swf?pselbtn={$selbtnno}&pbtn1menu={$val['text']}&pbtn1url={$val['href']}", "190","21",false);</script>
이렇게 변경했습니다.
<li>의 selected되었을 때 class를 on으로 변경하는 부분이 지워진 것입니다.
class가 on이어야 3차메뉴가 display되기 때문에 이부분을 생략한 대신 3차메뉴 부분에서
<ul <!--@if($val['selected'])-->style="display:block"!--@end-->
이 부분을 첨가했습니다.
그리고 새창열기 옵션은 사용하지 않는 것으로 전제하고 window.open 부분도 생략했습니다.

다음 변경된 부분에서 플래시 파일을 불러들일 때 url 옵션
http://주소/submenu1.swf?pselbtn={$selbtnno}&pbtn1menu={$val['text']}&pbtn1url={$val['href']}

변수 pselbtn과 값 {$selbtnno}
이 변수와 값은 레이아웃이 로딩될 때 메뉴가 선택되어 있는가의 여부에 따라 플래시 버튼에 다른 액션을 주기 위한 값입니다.
{$selbtnno}을 할당하는 부분은 위에서 찾으실 수 있을 겁니다.
pbtn1menu와 pbtn1url에 각각 메뉴 text와 메뉴 href를 할당합니다.

이제 첨부한 submenu1.swf를 사이트에 적당한 위치에 업로드하고
http://주소/submenu1.swf 주소 부분만 수정해서 쓰시면 됩니다..

더불어서 플래시 소스 파일도 올려 놓겠습니다.
한 층 세련된 디자인의 메뉴용 플래시 파일들이 올라오길 바랍니다.

맨 앞에서 적은 것처럼
한 파일에 여러개의 메뉴 버튼를 적용하려면
submenutest.fla처럼 메뉴 버튼 갯수를 조절해서 쓰셔도 됩니다.
by Anna 안나 2008. 6. 1. 20:36
별 기능은 아니지만 http://www.chelsea.name/zbxe/board Free Board 라는 제목 효과를 볼 수 있습니다.

파일은 2개 입니다. flash.js , board_tit.swf

사용하는 스킨 JS폴더에 flash.js 복사
board_tit.swf 파일은 ZBXE폴더에 넣어주시면 됩니다.


zbxe/modules/board/skins/사용스킨 header.html 파일을 열고
<!--%import("js/flash.js")--> 추가



그 다음은 제목 부분에...
<script language="javascript">
flash('550','30','board_tit.swf?flash_gallery_txt={$module_info->title}');
</script> <br/>

이렇게 사용하시면 알파값이 천천히 밝아지면서 제목이 나옵니다.
바탕색과 상관없이 사용가능합니다.

flash.js ((-------IMAGE-------))
by Anna 안나 2008. 6. 1. 20:34
IE7 의 렌더링 방식이 IE6과 다르다.
CSS testing of Selector and Pseudo selectors 를 보면 IE7 은 FF 에 더 가까와 지고 있다.
그래서 바야흐로 브라우저 3개를 켜고 코딩을 해야하는 시대가 온 것이다.

이를 해결하기 위한 방법 중 하나는 Selector Hack 을 이용하는 것이다. .context_bar_form_field
{
height: 15px; // 모든 브라우저
#height: 15px; // IE 전용
_height: 21px; // IE6.0 과 이전버젼용
} 우선 파폭에 맞추어 개발을 한 후 E7 에서 점검한다. 수정할 부분이 있다면 # 접두어를 붙여 수정해 준다. #이 붙은 것은 FF 에서 무시한다. 하지만 IE 는 재설정 해준다.
다음에 IE6 을 열고 수정하면서 _ 를 접두어로 붙여 새로 재설정 한다. IE7 은 '-' 가 붙은 것을 무시한다.

또 다른 방법은, .title h3 {height: 21px; }
.title > h3 {height: auto; min-height: 21px; }
이렇게 하는 방법도있다. 맨 아래줄은 파이어폭스와 IE7만 적용된다.

한가지 주의할 점은
body
{
text-align:-moz-center; /*FF*/
#text-align:center; /*IE */
}
속성 키워드 자체가 다른 것이 많다. 주의 할 것! 위에서 처럼 속성값 자체가 다른 경우가 있다. 그러니 안된다고 hack 만 쳐다보고 있으면 밤세야 한다.

내가 보기에 가장 좋은 방법은 Conditional Comments 를 사용하는 것이다.
복잡하게 한 파일에 구질구질 작성하지 말고 파일을 분리해 버리는 것이다.

참고 :http://webborg.blogspot.com/2007/01/css-compatibility-ie6-ie7-firefox-and.html
<head>
<title>my css hacked page</title>
<link rel="stylesheet" type="text/css" href="styles.css" />
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="iehacks.css">
<![endif]-->
<body>
<div class="watermark">....</div>...
이렇게 분리해서 각개격파하는 것이 좋을 듯 싶다. E 용인 Expression을 사용하여 본다면 a { expression(어쩌구 문법) } 이렇게 해서 a 태그 즉, 링크에 걸린 항목에 대하여 Expression은 적용 시킬 수 있을것입니다. 그럼 예로.. 링크주소중에 pdf 라은 확장자가 있다면 링크 앞에 자동으로 PDF 아이콘을 띄워봅시다. a {
padding-left: expression(this.href.indexOf('.pdf') > 0 ? '20px' : '');
background: expression(this.href.indexOf('.pdf')>0 ? 'transparent url(pdf.gif) no-repeat center left' : '');} 이건 IE 용입니다. Firefox에선 이렇게 하시면 됩니다. a[href $='.pdf']{
padding-left: 20px;
background: transparent url(pdf.gif) no-repeat center left;} 음... 불여시에서 사용하는게 훨씬 간편하네요 @@;; [href $='.pdf'] 이 구문에서 $는 .pdf로 끝나는 것을 의미합니다. .pdf로 시작하는 것을 찾으려면 $대신에 ^을 사용하시면 됩니다. [href ^='.pdf']가 되겠죠. 그냥 포함 되어 있는지를 찾는 거라면 *을 사용하시면 됩니다. <style>
a[href $='.pdf']{
padding-left: 20px;
background: transparent url(pdf.gif) no-repeat center left;}

a {
padding-left: expression(this.href.indexOf('.pdf') > 0 ? '20px' : '');
background: expression(this.href.indexOf('.pdf')>0 ? 'transparent url(pdf.gif) no-repeat center left' : '');}
</style> <a href="test.pdf">test1</a><br/><a href="test.gif">test2</a>
by Anna 안나 2008. 5. 31. 13:26
원문 보기
by Anna 안나 2008. 5. 30. 23:17
흔히 링크버턴 등에 생개는 점선을 없애기 위해서
onfocus='this.blur()' 라는 태그를 많이 쓰고 계시죠?
아래 소스는 단 한번 입력만으로 문서 전체에 점선 테두리를 없애는 스크립트입니다

<body> 와 </body> 사이에 입력 하세요.
by Anna 안나 2008. 5. 30. 23:04
<select name=Target1 style="font-family:굴림; font-size:10; color:#ffffff; background-color:#000000;">
<option selected>menu</option>
<option>menu1</option>
<option>menu2</option>
<option>menu3</option> </select> 링크 걸기
<select name=Target1 onblur="this.selectedIndex = 0" onchange="window.open(this.options[this.selectedIndex].value,'main')" style="font-family:굴림; font-size:10; color:#ffffff; background-color:#000000;">
<option selected>menu</option>
<option value=문서경로>menu1</option>
<option value=문서경로>menu2</option>
<option value=문서경로>menu3</option> </select> font-family : 글꼴
font-size : 글자 크기
color : 글자 색
background-color : 글상자 배경 색
onmouseover backgroundColor : 마우스를 가져갔을 때의 버튼 색
onmouseover backgroundColor : 마우스를 가져가지 않았을 때의 버튼 색
border-width : 테두리 투께
transparent : 투명
by Anna 안나 2008. 5. 30. 23:00
CSS hack 이란?
브라우저의 구현 차이나 버그를 이용하여 CSS의 적용대상에서 일부 브라우우저를 제외하거나, 특정 브라우저만을 대상으로 CSS를 적용하는 방법을 'CSS핵' 이라고 합니다.
크로스브라우징을 위한 응급대처 같은 방법이라고 생각하시면 되고, 핵일부는 CSS의 문법상 올바르지 않은 것도 있을 수 있습니다.

여러 핵들이 있지만, 자주 사용하는 핵을 살펴보겠습니다.

1. 스타핵 (star hack)
셀렉트 앞에 *html 을 붙히며 Win IE 4~6, Mac IE 4~5 등에 스타일이 적용되며 다른 브라우저에는 적용되지 않습니다.
view plaincopy to clipboardprint? *html p{ padding:3px; } /* 맨앞에 *html 을 붙혀줍니다. */ *html p{ padding:3px; } /* 맨앞에 *html 을 붙혀줍니다. */
2. 언더스코어 핵 (underscore hack)
속성의 가장 앞부분에 언더스코어(_)를 붙이며 Win IE 4~6 등에서 스타일이 적용되고 다른브라우저에서는 적용되지 않습니다.
view plaincopy to clipboardprint? p { _padding:3px; } /* padding 앞에 _ 를 붙혀줍니다. */ p { _padding:3px; } /* padding 앞에 _ 를 붙혀줍니다. */
3. 해시 핵 (hash hack)
속성의 앞에 # 를 붙이며 Win IE 4~6, Mac IE 5, Opera 7, Mozila, Firefox 등에 스타일이 적용되고 다른 브라우저에는 적용되지 않습니다. (CSS의 문법상 속성의 앞에 #를 두는 것은 문법적으로 바르지 않습니다.)
view plaincopy to clipboardprint? p { #padding:3px; } /* padding(속성) 앞에 #를 붙힙니다. */ p { #padding:3px; } /* padding(속성) 앞에 #를 붙힙니다. */
4. 스타 7 핵 (star 7 hack)
셀렉트 앞에 html* 를 붙이며 Win IE 5.5~6, Map IE 5, Safari 등에서 스타일이 적용되고 다른 브라우저에서는 적용되지 않습니다. html* 과 선택자 사이에 공백을 두시면 안됩니다.
view plaincopy to clipboardprint? html*p { padding:3px; } html*p { padding:3px; }
5. IE7 전용핵셀렉트 앞에 *:first-child+html 를 붙히며, IE 7에만 적용이 됩니다.
view plaincopy to clipboardprint? *:first-child+html p { padding:3px; } *:first-child+html p { padding:3px; }
이밖에도 브라우저 배제를 위한 핵과 박스모델 핵 패스필터 등이 있지만, 제가 주로 사용하는 핵을 위주로 적어봤습니다.

hack 을 자주 사용하면 새로운 브라우저에 영향을 끼칠수도 있으며, 업무효율을 떨어뜨리는 요인이 될수도 있으니, 응급대처 방법이라고 생각하시고 사용하시는게 올바른 판단이라고 생각됩니다.
by Anna 안나 2008. 5. 30. 22:59
-
by Anna 안나 2008. 5. 26. 18:14
크게 바뀐건 없습니다.,
1. 채팅방목록에 작은채팅창 - 0.1초후에 뜨도록 했고,
- - - 0.2초후에 체크해서 안떴으면 다시 뜨도록 하는거 --- 추가했고,

2. 폴더삭제 함수에서, 경로값끝이 / 이게 아니면, 추가하도록 했습니다.
- - - 예제에 보니까, 삭제된 채팅방인데 폴더가 남아있어서
- - - 에러나는 경우가 있던데, 그 문제를 잡은 것입니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:11
채팅방 예제에 보면
채팅방목록에 방문자목록없는 작은 채팅창이 있는데,
홈페이지나 등등에 넣어서 쓸수 있게,
그 부분만 짤라봤습니다.
소스길이는 143줄

다운로드 : http://www2.ssam.biz/blog/img/c.rar

아래가 소스입니다.
<?
session_start();
header ("Content-Type: text/html; charset=UTF-8");
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
if($_POST[xname] && $_POST[text]) {
if(!$_SESSION[name] || $_SESSION[name] != $_POST[xname]) {
$_POST[xname] = str_replace('<', '&lt;', str_replace(' ', '', stripslashes(trim($_POST[xname]))));
$_POST[xname] = preg_replace("` [\s]`i", "", $_POST[xname]);
$_POST[xname] = preg_replace("`[\x1b\x18\x7f\t]`", "", $_POST[xname]);
$nickc = "";
if($_SESSION[name]) $nickc = "--\x1b<font class=mc><font class=mm>".$_SESSION[name]."</font> → <font class=mm>".$_POST[xname]."</font>로 닉변경함</font>\n";
session_unregister("name");
$name = $_POST[xname];
session_register("name");
}
if($_POST[xname] && $_POST[text]) {
$_POST[text] = preg_replace("`[\x1b\x18\x7f<]`", "", stripslashes($_POST[text]));
$fp = fopen("./_text", "a");
fputs($fp, $nickc.$_POST[xname]."\x1b".$_POST[text]."\n");
fclose($fp);
if(filesize("./_text") > 2048) {
$fp = fopen("./_text", "r");
fread($fp, 1536);
fgets($fp);
while(!feof($fp)) $fpo .= fgets($fp);
fclose($fp);
$fp = fopen("./_text", "w");
fputs($fp, $fpo);
fclose($fp);
}
}
exit;
}
if($_GET[tex]) {
if(file_exists("./_text")){
if($_GET[tex] == -1) $_GET[tex] = 0;
$fze = filesize("./_text");
if($fze != $_GET[tex]) {
echo $fze."\x7f";
$fp = fopen("./_text", "r");
while(!feof($fp)) {
if($_GET[tex] && $fze > $_GET[tex]) fread($fp, $_GET[tex]);
if($fpo = trim(fgets($fp))) echo $fpo."\x7f";
}
fclose($fp);
}
}
exit;
}
if($_GET[delete] == "text" && $_SESSION[admin_pass]) {
$fp = fopen("./_text", "w");
fclose($fp);
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>채팅방</title>
</head>
<body>
<script>
function go() {
var url = '?tex=' + document.getElementsByName('ntim')[0].value;
if(window.ActiveXObject) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
var xmlHttp = new XMLHttpRequest();
}
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState==4 && xmlHttp.status==200) {
var str = xmlHttp.responseText;
if(str) {
var vew = str.split("\x7f");
allc = vew.length -1;
if(allc > 1) {
document.getElementsByName('ntim')[0].value = vew[0];
if(document.getElementById('AA').innerHTML == '') str = "<table border=0 cellspacing=0 cellpadding=0 width=100% style='margin-bottom:20;table-layout:fixed'>";
else str = "";
for(i = 1;i < allc;i++){
var nam = vew[i].split("\x1b");
str += "<tr class=trh><td class=name>"+ nam[0] +"</td><td width=10>:</td><td class=memo>"+ nam[1] +"</td></tr>";
str += "<tr><td colspan=3 bgcolor=#E6E6E6 height=1><img height=1></td></tr>";
}
str += "</table>";
document.getElementById('AA').innerHTML = document.getElementById('AA').innerHTML.substring(0,document.getElementById('AA').innerHTML.length-8) + str;
document.getElementById('AA').scrollTop = 10000000;
}
} else window.status = '새 글이 없습니다.';
setTimeout('go()', 1000);
delete xmlHttp;
}
}
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}

function wte(){
if(window.ActiveXObject) {
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else if(window.XMLHttpRequest) {
var xmlHttp = new XMLHttpRequest();
}
var param = '?&xname='+ document.getElementsByName("xname")[0].value.replace(/[&'"]/gi,"") +'&text='+ document.getElementsByName("text")[0].value.replace("&","%26");
xmlHttp.open("POST", param, false);
xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlHttp.setRequestHeader("Content-length", param.length);
xmlHttp.setRequestHeader("Connection", "close");
xmlHttp.send(param);
document.getElementsByName('text')[0].value = '';
document.getElementsByName('text')[0].focus();
return false;
}
window.onload = function(){setTimeout("document.getElementsByName('ntim')[0].value='-1';", 50);}
setTimeout('go()', 100);
</script>
<center>
<table border=0 cellspacing=0 cellpadding=5 width=330 style='border:1px solid black'>
<tr height=200><td colspan=3><div id=AA style='width:320;height:200'></div></td></tr>
<tr height=30><td colspan=3><input type=text name='xname' maxlength=10 style='width:65' value='<?=$_SESSION[name]?>'>
<input type='text' name='text' style='width:200;'>
<input type='submit' value='쓰기' onclick="wte()" class='button'>
<input type='hidden' name='ntim' value='-1'>
</td></tr>
</table>
</center>
<style>
body {font-size:9pt;font-family:gulim;word-break:break-all;}
td {word-break:break-all;font-size:9pt;}
.mm {color:#D7D7D7;font-weight:bold;font-family:gulim;text-align:center;padding-top:5}
.mc {color:#D7D7D7;font-family:gulim;text-align:center;padding-top:5}
.button {background-color:#D7D7D7;border:0;border:1px solid black;margin-right:4px;margin-left:4px;width:35px}
.name {width:50;padding-left:5;font-weight:bold;}
.memo {padding:5px 0px 5px 5px;width:210;}
.trh {padding:6px 0px 6px 0px;}
#AA {overflow-x: hidden; overflow-y: auto;background-color:#FFFFFF;border:1px solid black; }
</style>
</body>
</html>
보기 / 닫기

소스 53줄에 데이타초기화하는 부분이 있는데,
이건 각 홈페이지의 관리자만 가능해야 하니까,,
링크도 현재 안넣었습니다.

<a href='?delete=text'>본문초기화</a>
이렇게 링크를 적당한 곳에 넣어주면 됩니다.

인코딩이 이건 utf-8로 저장되어야 합니다.
아마 홈페이지들하고 인코딩이 다를거 같은데,
iframe으로 불러들이면 되잖을까 합니다.
높이가 고정된 것이니까..

소스에 데이타를 "_text" 파일에 저장하도록 되어 있는데,
하여튼 쓰기권한이 열린( -- 707 또는 777) 폴더로 경로를 잡으면 됩니다.
by Anna 안나 2008. 5. 26. 18:10
예제에 색깔이 바뀐게 젤 눈에 들어오겠는데,
소스위쪽에 색깔을 좀 더 다양화했습니다.
$color_1 ~ $color_6 까지.
이거외에 쓰인 색상은,, 채팅방목록에서 비번으로 잠긴방 표시하는 붉은(?)색밖에 없습니다.

기능적으로는 사소한거 몇가지 수정했습니다.
- - 파일업로드하면 - 업로드창 닫히는거 + 그러면서 포커스를 글쓰는 부분으로 주는거
- - 채팅방삭제 링크를 버튼으로 바꾼거
- - 강퇴버튼에다가 스타일준거
- - 비번걸린방 들어갈때 비번넣은 창- 조금 보기좋게 다듬은거
- - <b>,<i>,<s>,<u> 버튼(?) 눌렸는지 표시해서
- - 연속적으로 쓸수있게 한거
- - 폰트나 사이즈같은 태그지원항목 선택할때, 블록설정된 부분없으면 전체적용하도록 한거


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:10
기능적 오류 하나 찾아서 고쳤습니다.
FF에서 채팅방목록 - 실시간메모에 글이 안올라가는 문제.

그리고 디자인을 조금 바꿔봤는데,
...... 어떨라나 모르겠습니다.

외곽선 굵기나 외곽선 종류(solid,dotted,,) 배경색 같은거 수정하기 쉽도록 했습니다.
외곽선 굵기는 $w, 배경색은 $color_2, 나머지는 스타일class에..

수정해서 쓰기는 더 복잡해졌는지도 모르겠습니다.
table이 많아져서,, (삐쭉삐죽 모양 만드니라고)

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

((-------IMAGE-------))
by Anna 안나 2008. 5. 26. 18:08
78버전--에서 별다른 에러는 나타나지 않았습니다.
다만 어떤 경우에, 인코딩을 제대로 UTF-8로 인식하지 못하는 경우가 있더군요.
그래서 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
이 html소스를 추가했습니다.

78버전까지는 그냥 php에서
header ("Content-Type: text/html; charset=UTF-8");
이렇게 헤더주고,, 말았는데,,

어쨌거나,, 그거 하나 수정했습니다.

아 또,, 혹시 원인이 스타일소스에 폰트이름 "굴림"을 인식못해서 였을까 해서,
굴림을 gulim으로 바꿔봤는데,,,
원인이 그게 아니었지만,, 하여튼 그래서 폰트이름이 gulim으로 표시가 바뀌었습니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:07
77버전에서 - 방문자목록에서 닉네임을 클릭했을때,
귓속말하고,강퇴버튼이 있는 창이 안열리는 에러가 있었습니다.
알려주신 흠님., 감사드립니다.

뭔일인가 소스를 열어보니 어처구니없게도, </form>을 빼먹었더군요.
그래서 에러는 수정하고......

간혹 접속이 안좋은 경우에, 글은 올라가는데,
30초동안 방문자목록 접속이 없었다고 짤리는 경우가 있길래,
글을 올릴때, 방문자목록에 접속시간도 갱신되도록 했습니다.

대신에 방문자목록 접속간격을 새글확인 열번에 한번 -- 대략 10초마다 한번씩 하도록 했습니다.

...

사용자가 읽은 본문의 크기가 서버에 파일로 저장되니까,,,
혼자서 브라우저 두개 열어놓고 있으면- 제대로 출력이 안됩니다.
이쪽 브라우저에서 x만큼 읽어가면, 저쪽 브라우저에서는 그만큼 출력이 안됐는데,
이미 읽어간걸로 서버의 파일이 기록되어 있으니까, 그만큼 빼먹는거지요.
저쪽에서 읽으면, 이쪽에서 빼먹고......

브라우저하나로 사용해야 제대로 됩니다.


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:07
75버전까지는 인터넷회선 상태가 안좋을때는
- 퇴장했다,입장했다하는 문구가 자꾸 나왔는데,
(10초안에 접속이 없으면 그냥 나간걸로 표시했기 때문입니다.)

이번에는 window.onunload = function() {}
이렇게 onunload 이벤트에 함수를 실행시켜서,,
방문자데이타파일에 뭔가 기록을 하고,
그 상태로 갱신없이 10초가 지나면 나간걸로 판단하도록 했습니다.

10초 여유를 둔건, 브라우저 새로고침했을때도 그 이벤트가 발생하기 때문입니다.
그리고 FF에서 탭을 클릭해서 닫거나, FF자체를 종료시켜서 닫을때는
그 이벤트가 작동하지 않더군요.
(IE의 경우엔 모든 경우에 다 작동하던데)

그래서 그런 경우에 대비하기위해서
30초동안 접속이 없는 상태면 -
30초동안 접속이 없다고 표시하고, 나간걸로 판단하도록 했습니다.

프록시설정하고 테스트해보니까,, 그래도 30초동안 접속이 없었다고 표시되더군요.
((프록시가 워낙 늦고,상태가 안좋아서))

FF에서 새로고침하면
기존의 글이 안떴는데,
알고보니 FF에서는 새로고침해도, 출력된 인풋값들이 초기화되질 않는거 같더군요.
그래서 새글출력에 관련된 것들은 강제로 초기화되도록 소스를 넣었습니다.

기존에 새글읽는게, 그 파일크기를 클라이언트에 저장했다가,
그 값으로 호출해서, 파일크기가 그거보다 크면, 그 차이만큼 읽어오도록 했었는데,,,,,
프록시를 써서 해보니까,
워낙 상태가 안좋아가지고... 중복출력되는 경우가 가끔 있었습니다.
그니까 파일크기의 값이 서버에서 클라이언트로 왔다갔다하는게 잘 안되다보니까...

그래서 왔다갔다 안시키고, 그냥 서버에 저장되도록 했습니다.
(얼마만큼 읽어갔는지가 각자가 다르니까,, 사용자마다 각각의 파일로)
그래서 상태가 안좋아도, 중복출력되는 경우는 안생깁니다.

외관은 변하지 않았습니다.

--------------------

여기까지가 76버전의 설명이었습니다.
근데 76버전에서 파일업로드 문제가 발견되서,

파일업로드관련 문제랑, 몇몇가지 더.. 에러를 잡아서 77버전으로 올립니다.
76버전은 문제가 드러났으니까, 비공개하고..



mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:06
채팅방id가 숫자만으로 되면
"~~님이 입장하셨습니다" 라는 문구가 계속 반복되는 문제가 있었습니다.
....
$_SESSION[$id] 라는 것에 그 채팅방에 입장순번을 담아서
그 사람을 특정하고 있었습니다.
그래서 $$id = "_".순번; 이렇게 채팅방id자체를 변수로 만들어서,
session_register($id); 이렇게 등록하는데,,,,
예를들어 채팅방id가 1234라면,
$$id 가 $1234가 되어서,,, 변수가 성립하지 않는 문제였던거 같습니다.
(아마 $다음 첫글자가 숫자면 안되던가,,?? 였던걸로 기억납니다.)

그래서 자꾸 $_SESSION[$id]가 풀리면서
닉네임은 있되, 그 방에 새로 입장한 사람으로 판단하고
계속 "입장하셨습니다"라는 문구를 띄운 것입니다.

-- 그래서
$xd = "_".$id;
$$xd = "_".순번;
session_register($xd);
이렇게 바꾸고,
$_SESSION[$id] 대신에 $_SESSION["_".$id]로 호출하도록 바꿨습니다.
(요런거 할줄 몰랐는데, 필요해서 해보니까 되는군요)
더불어서 채팅방개설자를 구분하는 세션값도
비슷한 과정으로 조금 변동을 줬습니다.

채팅방id가 숫자라도, 변수로 쓸때는 앞에 "_" 이게 위치하니까
이제 에러가 안납니다.


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:06
대충 1초당 한번꼴로 서버에 접속해서
(GET으로 접속-출력된 filesize정보 보냄)
----- filesize가 보내온거하고 다르면
----- 새로 올라온 글이 있으면, filesize가 그만큼 늘어났을테니까
----- 그 차이만큼만 읽어오고,
----- 아니면
----- 구분자만 가지고 오는데,
----- 그 접속 다섯번에 한번 꼴로
----- 방문자목록 데이타를 읽고,편집,기록 합니다.
----- 방문자가 입장한 경우엔, 자기가 접속해서, 자기가 기록하지만
----- 퇴장한 경우엔, 그 사람은 이미 나갔기 때문에
----- 방문자목록에서의 삭제는 다른 사람의 접속때 이뤄집니다.
----- ----- 그래서 예제-채팅방에서 혼자 있다가, 나간경우 퇴장했다고 표시가 안됩니다.
----- ----- 그리고 중간에 다른 사람이 들어오지 않은채로, 다시 들어왔을때는
----- ----- ip나 같거나, 세션이 살아있으면, 동일인으로 취급해서, 역시 퇴장표시가 안됩니다.
.....

실제로 읽어오는 자료의 양은 많지 않습니다.
5초마다 한번 방문자목록,
----- 방문자의 닉네임하고 1byte짜리 구분자셋하고 그 사람의 순번세션값(99번 안쪽이면 3byte)
----- 닉네임이 한글이면 utf-8에서 3byte인데(여기서는 2byte인지 3byte인지 모르겠지만, 하여튼 3byte 잡고)
----- 닉네임이 한글 네자면 12 + 구분자 셋 3 + 순번값 3 = 18
----- 넉넉하게 한 사람에 20byte
----- 열명이면 200byte
----- 1초당으로 나누면, 40byte
그리고 새글이 올라왔을때, 올라온 글과 파일의 새크기.
----- 파일의 크기는 10240byte면 백업하고, 새로 생성하니까
----- 5자리까지 거의 안가고, 넉넉잡아 4byte
----- 1초당 새글이 한글 20자(3byte로 계산) 60byte 잡고,
----- 60byte + 구분자 두개 + 파일크기 4 + 방문자 초당 40 = 106
----- 106byte 인데,,,
----- 아주 많이 넉넉하게 잡아서 200byte라고 했을때,
----- 1시간 = 3600초로 계산하면
----- 703.125kb
----- 열명 잡았으니까 그거 열배라고 한다면 7031.25kb = 6.8664MB
----- 1시간 열명사용에 트래픽이 대충 7메가바이트
----- 라고 계산되는데.

트래픽 분석하는 프로그램으로 보면
혼자 예제에 방을 열어두고, 아무 글도 안올라오는 상태여도
초당 한 1KB쯤 되더군요.
내용말고 헤더정보 때문에,.

그래서 헤더정보가 트래픽계산에 들어가는지 궁금해서
찾아봤더니 - 못찾겠더군요.

혹시 이거 트래픽에 들어간다고 하면,
넉넉잡았을때 초당 200이 아니라, 1200으로 잡아야 합니다.
그럼 위의 계산보다 6배....
6.8664MB * 6 = 41.198MB

그니까 헤더정보가 포함된다고 할때
1시간동안 열명이서 넉넉하게 썼을때,
열명의 접속을 다 포함해서 41MB
by Anna 안나 2008. 5. 26. 18:05
알고보니 레이아웃을 박살내고
채팅방을 못쓰게 만들수 있는 태그가 많더군요.

그래서 고심끝에
위지윅으로 바꿔봤는데,
키보드로 내용을 치고, 바로 엔터(키보드)를 누르면
줄바꿈으로 가는 겁니다.. submit이 안되고,,

어찌저찌 onkeydown을 캡춰해다가, 이벤트를 걸어서 해볼라고도 해봤는데,
불안정적이더군요. 이벤트를 잡았다가 못잡았다가 하고...
-- 위지윅에서 글이 작성되는 곳은 iframe안의 공간이라서...
FF에서는 특히 더 안되고...

해서 위지윅은 포기하고,
위지윅은 아니고, 소스가 나열되는 식이긴 하지만, 여튼 비슷하게 태그지원기능을 해놨습니다.
그래서 거기서 버튼이나 선택상자로 추가한 html태그가 아닌 것은
거의 걸러서 작동하지 않도록 했습니다.

<img src=''> <a href=''> 이것도 안먹힙니다.
이미지를 넣거나, 링크를 걸고 싶을때는 그냥 http://~~ 주소를
내용에 넣어서 올리면 됩니다.


태그지원기능- 은.
그냥 이게 일회적인 게시판과는 달리,, 연속적인 성격이 있기 때문에,.
이전에 색상 선택하면 계속 이어졌듯이..
어떻게 할거냐... 고심을 했었는데,

내용중에 일부분을 블록(마우스긁음)으로 선택하면
그 영역안에만 적용되도록,
그렇지 않은 경우에는 전체적으로 적용되도록 했습니다.

연속성을 갖는건, 색상, 글꼴, 글자크기 입니다.(선택상자로 된 것)
딱히 영역을 선택하지 않고, 이 셋중에 하나를 선택했을때는
내용에 아무 변화가 없지만,
선택한 값이 $_POST로 전송되서, 올린글을 처리할때 전체를 감싸게 됩니다.

연속성이 없는 b, i, s, u 의 버튼은
영역을 따로 블록으로 잡지 않았을때, 전체적으로 앞뒤로 쌉니다.
--- 소스에 이미지를 되도록 포함하지 않을려고, span에다가 스타일로 버튼 비슷하게 만들었는데,
보기 싫으면 이미지파일을 만들거나 해서 바꿔주시면 됩니다.. (소스 726줄 근처)


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

((-------IMAGE-------))
by Anna 안나 2008. 5. 26. 18:04
- - '실시간메모'라고 이름붙였는데, 채팅방목록에
방문자리스트없는 간단한 채팅방을 달았습니다.
내용이 2KB에 도달하면, 512byte만 남기고 나머지는 삭제합니다.-채팅방에서처럼 백업되는게 아니라-
그래서 덩치가 거기서 더 불어나지 않으면서 계속적으로 존속합니다.
저장파일은 chat폴더안에 _xext
관리자가 저장파일 삭제-리셋할수 있는 버튼을 달았습니다.
금지닉네임 제한은 하고, 금칙어 제한은 안걸었습니다.
본문에 html태그는 허용되지 않습니다.

- - 글올리는 자바스크립트함수에서 군더더기로 남아있던거 지웠고...

- - $_POST로 올라온 닉네임에서 이것저것 삭제하고,
금지닉네임하고 같은지 판별하는 과정을
종전엔 모두 다 거치게 했었는데,,
세션닉네임이 없거나, 세션닉네임과 $_POST로 올라온 이름이 다른 경우에만 그 과정을 거치도록 수정...

- - 치명적인 실수 수정
$dpi=foepn()으로 열었다가 fclose($dpi)로 닫지 않고, fclose($dph)로 해둔 오류 발견
자칫하면 파일이 삭제되는데,, 이런 실수가 있었더군요. 바로잡았습니다.

- - 닉네임에는 탭문자 모두 삭제, 공백문자만으로 된 경우도 삭제합니다만
본문에는 삭제하지 않습니다. 어찌보면 그것도 표현의 방법일수 있기 때문에...
단,, 채팅방 레이아웃이 깨지는 것들은 막았습니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:04
1. 강퇴당했을때, 채팅방목록으로 돌아왔다가, 재차 클릭했을때
기존엔 화면에 x 글자 하나 있었는데, 다시 채팅방목록으로 되돌아오도록(자바스크립트로) 수정했습니다.

2. 금칙어 서버에서 처리하던걸, 자바스크립트로 되도록 바꿨습니다.
서버부하를 줄이고, 서버의 처리속도를 올리기 위해서.

3. 중복되는 내용 막는걸, 서버에서가 아니라 자바스크립트로 클라이언트에서 이뤄지도록 바꿨습니다.
역시 서버부하를 줄이고, 서버의 처리속도를 올리기 위해서.

4. 71버전에서 "채팅방아이디_순번" 형태였던 $_SESSION[$id] 값을 "_순번" 형태로 바꿨습니다.
줄어든만큼 트래픽이나 처리속도가 좋아집니다.

5. 체감속도를 빠르게하기 위한 여러가지 조치가 있었습니다.
체감속도를 빠르게하면서 또한, 안정적으로 동작하게 하기 위해서
자바스크립트의
new Date(); getTime(); 함수를 이용해서 1/1000 초까지 측정한 값을 사용합니다.

글을 확인하고-읽어오는 주기가 있는데
소스의 6번줄 $refresh = 1000; 이 값입니다. = 1초.
글을 확인하고 setTimeout으로 다시 호출하면서, 그 시점의 시간 + $refresh 값을 어딘가 저장합니다.

글을 작성완료했을때, 역시 그 시점의 시간을 재서,
앞서 저장된 시간(= 새글확인할 예정시간)이 가까우면(=0.25초 이하) 그냥 기다리고,
멀면(=0.25초 초과) 그 즉시 새글확인하는 함수를 호출합니다.

이렇게해도 같은 내용이 중복출력되는 등의 문제가 있길래,
글을 올린시점의 시간을 어딘가에 저장하고, = 새글확인을 호출한 시간
다시 글을 작성완료했을때의 시간이 먼저번에 작성완료한 시간에 너무 가까우면(0.35초이하)
새글확인하는 함수를 호출하지 않도록 했습니다.

소스의 586줄에 "350" 이란 숫자가 그겁니다.

하여튼 투다다닥하고.. 예제에서 테스트해봤더니,,
내용이 중복출력되었을때는 새로고침하면 줄수가 줄어드는데,,
그런 문제가 더이상 안보이더군요...

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:03
1. 전버전부터 본문에 시간표시되도록 했는데, 채팅기록에는 적용되지 않았던걸 고쳤습니다.

2. FF에서 padding이 <tr>에 안먹는거 때문에, 닉네임나오는 <td>에 padding:5px 0px 5px 0px를 줬었는데,
이름이 없는 경우 (안내문)도 있어서 본문에 걸었습니다.

3. 채팅방에 입장하는 사람의 ip를 전부 기록해서, 입장순으로 번호를 메겨서 세션에 저장하고,
그 번호로 그 사람을 특정하도록 했습니다. ip나 세션아이디를 대체해서..
입장순으로 발급하는 세션값이 없을때, ip저장된 파일을 열어서, 중복되는 ip가 있는지 확인하고,
없으면 새 번호, 있으면 그 ip가 있는 순서의 번호로 세션을 생성합니다.
ip가 중간에 달라지더라도, 세션값이 있으면 계속 동일인으로 간주합니다.
(이 값은 "채팅방아이디_번호"로 되어있고,
--그러고보니 굳이 이럴필요까진 없었군요,그냥 번호만으로도 충분할걸--
호출하는 값이 $_SESSION[$id]라서, 다른 방에서 만들어진거와 중복되질 않습니다.$id가 다르기 때문에)

4. 닉네임 바뀌었다는 안내문을 고쳤습니다.
다른 채팅방에 들어갔다가 닉을 바꾸고, 다시 그 채팅방으로 들어오는 경우에도 안내문이 뜨도록 했습니다.
물론 그냥 닉네임을 바꾸는 경우에도 뜹니다.

// 하여튼 내부적으로 많이 달라졌습니다. 외관은 달라진게 없지만...

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

((-------IMAGE-------))
by Anna 안나 2008. 5. 26. 18:03
우측에 작게 시간표시(시:분) 되살렸습니다.
본문에 ..........................................................................................~~계속~~................
이렇게 넣으니까 레이아웃이 깨지길래,
table-layout:fixed를 내용출력되는 테이블에 추가했습니다.

그렇게하니까
내용이 길때도 tr height=24 로 고정되고 글이 안보이길래,
height 정의한거 지우고 <tr class=h> 로 해서,
아래쪽에서 padding:6px 0px 6px 0px을 줬습니다.

그렇게했더니,
FF에서는 안먹히길래, <td class=n>에 padding:5px 0px 5px 0px 줘서
대충 ie랑 비슷하게 맞췄습니다.

session_id()를 보조적으로 사용하도록 했습니다.
중간에 ip가 바뀌는 경우에도 "퇴장했습니다. 입장했습니다" 하는게 반복되지 않도록..

귓속말 받은거 볼때는 여전히 ip를 기준으로 합니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:02
요구사항을 반영해서
ie6에서 먹히는 src="javascript:
ie7에서도 먹히는 href="javascript:
를 막았습니다.

그리고 내부적으로 구분자를 바꿨습니다.
(키보드상에 있지만, 기록될수 없는 문자 \x1b등으로)
-- 그래서 소스가 대폭적으로 수정되었습니다.

소스 9번줄부터
채팅에 쓰이는 색상 네가지를 변수로 담았습니다.
색상을 바꿀때 거기만 바꾸면, 전체적으로 바뀌도록 했습니다.
그 이상의 수정을 원할때는
이거에다가 소스 맨 아래쪽에 스타일부분 수정하면 어느정도 될거 같습니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:02
요구사항을 반영해서,
닉네임을 공백만으로는 설정되지 않도록,
닉네임에 <를 &lt;로 바뀌도록해서 태그사용 못하도록,
그리고 본문에 iframe 못쓰도록,
운영자는 금칙어제한을 받지 않도록
수정했습니다.


본문에 태그를 제한하는 부분은
소스 280줄에
$_POST[content] = preg_replace('`<(/?)(sc|!|co|t|if|x|p)`i', '&lt;$1$2', $_POST[content]);
이 부분입니다.
script, 주석, comment, textarea(table tr td), iframe, xmp, pre를 막기위해서 저렇게 설정했습니다.

그리고 채팅방개설할때 채팅방id 적는부분은 한글전환이 안되도록 했습니다.
(스타일에 ime-mode:disabled 추가해서)
비밀번호는 한글도 됩니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.

by Anna 안나 2008. 5. 26. 18:02
"퇴장하셨습니다. 입장하셨습니다."
하고 나오는 방문자목록에서의 오류를 최대한 잡아봤습니다.
그 부분에 소스가 바뀌었습니다.

아마 이번에는..


mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:01
채팅방 예제에서 보다보면,
"xxx님이 입장하셨습니다. 퇴장하셨습니다." 하는 구문이 너무 자주 나와서
보기가 좋지 않길래.
body에다가 onload, onUnload 이벤트에 걸었던거 삭제하고,
방문자목록에 연동해서 처리하도록 했습니다.

그리고 방문자목록에서 처리할때,
동일인이 퇴장하셨습니다. 입장하셨습니다. 이렇게 나오는 경우 많은데,
ip가 같으면 시간불문하고 그렇게 표시되지 않도록 했습니다.

방문자목록확인은 대략 4초// 새글확인 네번째마다// 되도록 했고,
방문자기록에서 삭제는 현시간 - 10초로 좀 넉넉하게 했습니다.

혼자서 테스트하느라고, FF에 프록시설정해서 해보니까,
프록시때문인지 너무 늦어서, 넉넉하게 줬음에도 자꾸 들어왔다니, 나갔다니 하는 표시가 되더군요.
뭐 워낙 접속속도가 느리니까 그랬던 것이고,
일반적인 접속환경에서는 거의 그럴일이 없을겁니다.

하여튼 그래서 좀 더 안정성을 높였습니다.

외관은 변한게 없구요.
내부적으로 수정된게 있으니까,,
디자인 수정해서 쓰시던 분들은 이전 버전하고 대조해서 수정하시기 바랍니다.

mysql 안쓰고, php파일 하나로 돌아갑니다.
압축풀어 폴더채로 업로드하고, chat폴더권한 777주고(설치끝),
index.php에 접속해서 사용하면 됩니다.
by Anna 안나 2008. 5. 26. 18:01