'03.HTML 4.X, HTML5, XML...'에 해당되는 글 234건

  1. 2009.07.02 Web Hacking 3탄 구멍난 자바스크립트
  2. 2009.07.02 쿠키취야점을 이용한 해킹...
  3. 2009.07.01 마우스 오버시 말풍선
  4. 2009.06.27 [javascript] 입력 문자 한글 체크
  5. 2009.06.20 javascript get 방식으로 데이터 받기
  6. 2009.06.20 JavaScript] [브라우저]브라우저명을 정확히 알아내기
  7. 2009.06.18 html textarea 에서 엔터 값을 자동 줄바꿈으로 처리하는 방법
  8. 2009.05.13 css 버튼 모음
  9. 2009.05.11 php rss parser
  10. 2009.04.25 문자열 자바스크립트에서 금액표시하기 JavaScript
  11. 2009.04.25 자주쓰는 자바스크립트 함수
  12. 2009.04.24 javascript : CalendarView
  13. 2009.04.21 HTTP 1.1 통신규약
  14. 2009.04.18 javascript print
  15. 2009.04.16 네이버 콤보스타일 셀렉트 메뉴
  16. 2009.04.16 엑셀처럼 리사이즈 되는 td 만들기 table
  17. 2009.04.16 네비게이션 메뉴바 만들기
  18. 2009.04.13 달력 스크립트
  19. 2009.04.10 접근성을 해치지 않는 자바스크립트의 사용
  20. 2009.04.07 rownum 으로 범위지정을 해주고 싶을 때
  21. 2009.04.07 현재페이지를 알아오는 방법
  22. 2009.04.07 쿠키정보를 확인하고 활용할수 있는 코드
  23. 2009.04.07 새창을 데이타 크기에 따라서 자동조절되는 프린트 화면
  24. 2009.04.07 javascript 디버깅 툴 - Companion.JS
  25. 2009.04.07 javascript 에서 html value 값을 버전관계없이 바꾸고 싶을때
  26. 2009.04.07 동적으로 테이블을 추가하는 방법과 Disable 처리 예제 1
  27. 2009.04.07 javascript 에서 input 값에 숫자이외의 글 입력막기
  28. 2009.04.07 Javascript 에서 알아야할 기초사항
  29. 2009.04.07 프로젝트 나가서 주로 공통으로 쓰는 javascript common.js 내용
  30. 2009.04.04 GET POST 방식 깔끔 정리
반응형

Web Hacking 1탄 SQL Injection

Web Hacking 2탄 파일조작

Web Hacking 3탄 구멍난 자바스크립트



1. 시작하기

여러분들은 사용자가 입력한 값에대해 어느정도 검증을 하는지요?

사용자 값을 이것저것 따지고 여러가지 유효성을 체크할려면 아주 귀찮은 일이 아닐수 없습니다

그중에 하나가 웹브라우져에서 실행되는 자바스크립트로 체크하는 방법이 있는데 비지니스 로직이 조금 복잡할때는 자바스크립트로 도배를 하는 경우도 종종 있지요

유효성 검증하는일 저도 정~~말 싫어합니다 하지만 해야 합니다 ㅠ.ㅠ

그럼 어디까지 그 유효성을 체크해야 할까요? 자바스크립트로만 체크하면 될까요?


처음 웹프로그래밍을 할때는 저도 자바스크립트로만 입력값을 검증하면 되는줄 알았습니다

한마디로 몰랐죠

하지만 이제는 알기때문에 자바스크립트뿐만 아니라 서버쪽에서도 동일하게 체크해 주어야 합니다

사용자가 입력한 값이 얼마나 무서운지는 앞의 1탄, 2탄의 강좌를 통해 어느정도는 감을 잡으셨으리라 생각하고 이번 강좌에서는 왜 서버쪽에서도 체크해야 하는지!에 대해 간략히 알아보겠습니다



2. 자바스크립트 체크


입력값의 자리수가 13자리인지 체크하여 맞으면 submit을 만약 그렇지 않다면 정상적인 입력값을 요구하는 입력갑검사 로직이 있다고 가정하겠습니다 그리고 서버쪽에서는 꼭 13자리가 넘어와야 정상적인 처리를 할수 있다고 하겠습니다

그럼 아래와 같은 간단한 코드가 나올겁니다


http://www.jakartaproject.com/html/input.html

<script>

/* 입력한값이 13자리인지 체크 후 전송 */

function validateValue() {
    var obj = document.f.register_no;
    if (obj.value.length != 13) {
        alert('주민번호 정상적으로 입력하세요');
        return false;
    }
}

</script>


<form name=f method=post action=process.jsp onsubmit="return validateValue()">
주민번호 <input type=text name=register_no> <input type=submit name=btn value=submit>
</form>


 실제 웹 브라우져에서 보면 아래와 같습니다

"33" 이라는 두자리 수만 입력하니 역시나 재입력을 요구하는 alert창이 떳습니다 (가끔 깜짝깜짝 놀라죠 -,-)




그럼 정상적으로 "1111111111111" 의 입력값 13자리를 입력해 보겠습니다




 

그리고 이 값은 process.jsp 라는곳에서 파라미터로 받아 아래와 같이 처리합니다

코드는 간단하게 그 입력값과 레퍼러 값을 보여주겠습니다


http://www.jakartaproject.com/html/process.jsp

<%@ page contentType="text/html; charset=euc-kr" %>


<%
String register_no = request.getParameter("register_no");
%>


헤더정보 <%=request.getHeader("referer")%><br><br>
주민번호 <%=register_no%>


request.getHeader("referer")는 헤더정보에서 referer값을 가져오는 함수로, 이전 페이지 주소값을 가져옵니다

그럼 화면은 아래와 같이 나옵니다


자 정상적으로 처리되었습니다



3. 자바 스크립트 우회

그럼 이제부터 자바스크립트로 입력값의 자리수 체크로직을 피해가는 방법을 알아봅시다

어떤 방법이 있을까요?


URL로 접근

입력값이 몇가지 되지 않는다면 아래 방법이 가장 편하겠군요

즉 브라우져 주소창에다 직접 입력 합니다


http://www.jakartaproject.com/html/process.jsp?register_no=2222

아래와 같은 화면이 나올겁니다

메쏘드정보 (request.getMethod())를 찍어보니 GET 이 나오는군요!

그렇다면 이같은 직접 URL값을 막기위해 간단히 POST만 허용하는 로직을 추가해 버립시다


http://www.jakartaproject.com/html/process.jsp

<%@ page contentType="text/html; charset=euc-kr" %>


<%
if (!"POST".equals(request.getMethod())
   return;

String register_no = request.getParameter("register_no");
%>


헤더정보 <%=request.getHeader("referer")%><br><br>
주민번호 <%=register_no%>

이러면 괜찮겠지 흐흐.. 라고만끝나면 안됩니다


로컬파일로 접근

①번의 방법은 GET방식때문에 막혔습니다 그러면 자바스크립트를 우회하면서 POST방식으로 보내는 방법은 없을까요? 물론 있습니다

웹브라우져는 "소스보기" 라는 좋은 메뉴가 있습니다 있는건 적극 활용합시다 ㅎㅎ

소스보기한 후 바탕화면에 저장하여 약간 손을 보았습니다

즉 입력값을 체크하는 자바스크립트를 무력화 시키면서, action을 수정해 주었습니다


C:\Documents and Settings\Administrator\바탕 화면\client.html

<script>

/* 입력한값이 13자리인지 체크 후 전송 */

function validateValue() {

    return true;
}

</script>


<form name=f method=post action="http://www.jakartaproject.com/html/process.jsp" onsubmit="return validateValue()">
주민번호 <input type=text name=register_no> <input type=submit name=btn value=submit>
</form>



웹화면은 다음과 같겠죠


"submit"버튼을 클릭합니다 ^^


역시나 자바스크립트를 거치지 않고 process.jsp에 13자리수가 아닌 "22"값을 무난히 보냈습니다



그럼 서버쪽에서는 "어이쿠 이런 헤더정보도 체크해야 겠군" 하고 다음 코드를 추가해 버릴겁니다

즉 레퍼러값이 null인 경우는 허용할수 없다는 것이죠


http://www.jakartaproject.com/html/process.jsp

<%@ page contentType="text/html; charset=euc-kr" %>


<%

if (!"POST".equals(request.getMethod())
   return;


if (request.getHeader("referer") == null)
   return;

String register_no = request.getParameter("register_no");
%>


헤더정보 <%=request.getHeader("referer")%><br><br>
주민번호 <%=register_no%>

그럼 위와같은 소스가 될것입니다

그럼 과연 위 소스가 안전할까요?


HEADER값 조작

그렇다면 HEADER값을 조작해 봅시다 어떻게 조작할 수 있을까요?

여러가지 프로그램들이 있지만 그중에 Achilles 라는 proxy server를 이용하여 조작해 보겠습니다

Achilles라는 proxy server는 웹브라우져와 서버간의 HTTP 세션을 중간에서 가로채어 원하는대로 수정한 후 보낼수 있도록 해주는 작으면서도 강력한 프로그램입니다


※ 참고

Achilles 문서를 보면 맨 첫줄에 나오는 문장입니다

"Achilles is a tool designed for testing the security of web applications"

이 프로그램은 웹어플리케이션의 보안 테스팅을 하는데 작성되었으므로 테스팅용으로만 사용합시다


다운로드

http://www.mavensecurity.com/achilles


우선 위에서 작성한 바탕화면에 저장된 C:\Documents and Settings\Administrator\바탕 화면\client.html 를 실행한 결과를 Achilles가 Intercept한 결과입니다

여러 가지 헤더정보들이 보이며 쿠키값까지 조작할수 있습니다

하지만 위의 헤더정보에는 referer값이 없습니다 그래서 referer체크에서 null이 나와 로직에 걸립니다

그렇다면 referer정보를 추가해 줍시다


파랑색으로 줄쳐진 부분을 에디팅하여 추가해주었습니다

Referer: http://www.jakartaproject.com/html/input.html

그런다음 "Send"버튼으로 전송합니다


짠~

그러면 조작된 헤더정보를 알아채지 못하고 헤더의 referer값을 가져오는군요!



4. 서버쪽 로직 추가!

위에서 자바스크립트를 우회하는 몇가지 방법들을 알아보았습니다

결론은 하나입니다 즉! 서버쪽에서도 동일하게 체크해 주어야 합니다


<%@ page contentType="text/html; charset=euc-kr" %>


<%

String register_no = request.getParameter("register_no");


if (!"POST".equals(request.getMethod())
   return;


if (request.getHeader("referer") == null)
   return;


if (register_no.length() != 13)

   return;
%>


헤더정보 <%=request.getHeader("referer")%><br><br>
주민번호 <%=register_no%>


그렇다면 서버쪽에서만 체크하고 클라이언트에서는 체크할 필요가 없다고 생각할지도 모르지만,

그만큼 서버쪽으로 오는 request를 줄이면 더더욱 좋겠죠

자잘한것 하나때문에 서버쪽 부하를 줄수 없는 노릇아니겠습니까?


자 이러이러 하고 저러저러한 이유로 우리는 이제부터라도 클라이언트에서는 자바스크립트로,

서버쪽에서는 또 서버쪽 스크립트로 사용자가 입력한 값에대해 유효성을 검증해야 하는것을 알았습니다

로직이 복잡한 경우 가뜩이나 자바스크립트도 복잡한데 그 로직을 서버쪽에서 다시한번 만든다는게 힘들다는거 다들 압니다 하지만 안전한 웹페이지를 만들기 위해 다같이 노력해야 되지 않겠습니까?


Web Hacking 1탄 부터 이번 3탄에 이르기까지 웹 프로그래밍 하면서 반드시 필요하고 인식해야 하는 부분에 대해 논하였습니다

마지막으로 다시한번 언급하자면 우리가 잠깐 잊고 지나가거나 혹은 귀찮아서 지나치는 사소한 부분들 때문에 엄청난 결과를 가져올 수 있다는 것입니다 미리미리 예방하고 예측해서 방지하는수 밖에 없습니다 그럼 다들 건승~!~!


이상 GoodBug였습니다~


=============================================

본문서는 자유롭게 배포/복사 할수 있지만

이문서의 저자에 대한 언급을 삭제하시면 안됩니다

저자 : GoodBug (unicorn@jakartaproject.com)

최초 : http://www.jakartaproject.com 

=============================================

Posted by 1010
반응형

말도많고 탈도많은 쿠키!! 어떻게 사용하면 잘사용 하는걸까요?

앞으로 나오는 document.cookie등은 자동으로 "no_"앞에 가 붙습니다

Unicorn3에서 보안상 필터링하게 되어있기 때문입니다 앞에 "no_"가 없는것으로 간주하시면 됩니다


쿠키취약점

쿠키로 인증하는 사이트에 접속하여 로그인한 후 쿠키값 확인을 해봅니다

javascript:alert(document.cookie)


로그인 하지 않은 상태라면 다음과 같이 세션 아이디만 나오게 되며



로그인 한 상태라면 다음과 같이 쿠키이름과 쿠키값을 쌍으로 정보가 출력됩니다




관리자 아이디가 goodbug 라고 가정하고 이 아이디로 조작하기 위해서는 다음과 같이 입력합니다

javascript:a=prompt(document.cookie,"");alert(document.cookie=a)

그럼 프롬프트창이 하나 나타나며 이 부분에 다음과 같이 입력합니다



어떤 쿠키이름이 아이디를 나타내는 것일까요?

몇가지 없으니 가장 유력한 이름부터 하나씩 해보면 됩니다

UID=goodbug


다시 javascript:alert(document.cookie) 를 통해 쿠키값을 확인합니다


UID가 goodbug로 변경이 되었습니다

즉 내계정을 통해 goodbug로 로그인한것과 동일한 효과를 가져왔습니다!!

만약 쿠키로만 인증하는 방식이라면 타계정의 접속이나 관리자 화면으로 쉽게 들어갈 수 있습니다



 쿠키를 이용한 SQL Injection

쿠키를 이용하여 일반 로그인 화면이나 관리자 화면을 통화할 수 있습니다

SQL Injection이 어느정도 알려졌기 때문에 로그인 폼으로 부터 넘어온 아이디나 비밀번호 정보들을

일정 값들로 치환하는 경우를 볼 수 있습니다

즉 '나 ", -, \ #등의 SQL Injection에 활용되는 문자들을 무력화 시키곤 합니다

하지만 이역시 쿠키 SQL Injection을 통해 간단히 통과할 수 있습니다


마찬가지 방법으로 자신의 계정으로 로그인 하여 쿠키를 생성 한 후 다음과 같이 값을 변경합니다

UID=goodbug' or 1=1 --

관리자 화면은 화면마다 아이디를 이용해 인증을 할것입니다

하지만 이 관리자 아이디를 쿠키로 읽어온다면 아마 많은 허점이 생길겁니다

보통 쿠키로 부터 읽어온 값은 '나 --등은 체크하지 않죠

그래서 인증 관련된 부분은 항상 "특정문자를 치환+Statement" 보다는 "PreparedStatement"를 사용해야 합니다



 쿠키취약점 보안 및 결론

 -. 쿠키에 값을 구울때는 그 값을 "암호화" 하여 저장하고, 다시 읽어올때는 "역암호화"하여 사용합니다

 -. 로그인시에 IP도 쿠키에 같이 구워버리고, 데이터베이스에도 저장하며, 항상 실제 아이피와 비교하여 사용합니다

 -. 쿠키는 웹서버가 클라이언트에 남겨놓은 정보입니다

     그래서 쿠키는 클라이언트가 마음대로 조작하는것이 가능하기때문에 서버는 어떤일이 일어나는지 검사해야 한다는 것입니다


ps. 대형사이트에서는 IDS에 걸릴수 있으니 주의하세요


=============================================

본문서는 자유롭게 배포/복사 할수 있지만

이문서의 저자에 대한 언급을 삭제하시면 안됩니다

저자 : GoodBug (unicorn@jakartaproject.com)

최초 : http://www.jakartaproject.com 

=============================================

Posted by 1010
반응형

 
 
How To Use The Script

1. Download the library
Download wz_tooltip.js and unzipp it.
DHTML: Tooltips via JavaScript  
Top of page
 
Features
 
Cross Browser
 
Documentation
 
Extensions
 
Download
 
 
 
2. Link wz_tooltip.js into the html file

Copy the following line to inside the BODY section, preferably immediately after the opening <body> tag:
<script type="text/javascript" src="wz_tooltip.js"></script>
If necessary, adapt the path 'src="wz_tooltip.js"' to the JavaScript file. Note: Use the downloaded file only, do not hardlink wz_tooltip.js from my site.  
 
3. Specify tooltip text inside onmouseover eventhandlers

Each of the html tags to display a tooltip requires an onmouseover and an onmouseout attribute like so:

<a href="index.htm" onmouseover="Tip('Some text')" onmouseout="UnTip()">Homepage </a>

That's all. No title attributes, no container DIV. As you can see, the text to be displayed must be enclosed with single quotes, and be passed to a function Tip(). Attention: Single quotes (apostrophes) inside the tooltip text each must be masked with a backslash. Example:
Tip('This text won\'t trigger a JavaScript error.');
 
The call of UnTip() in the onmouseout eventhandler is to hide the tooltip again.
 
Of course you may also use different eventhandlers for Tip() and/or UnTip().


 
 
4. Doesn't Work?
a) Check the (dynamically generated?) HTML and the CSS of the page, preferably with the W3C Online Validator at http://validator.w3.org/. DOM errors will probably break the script.
b) Verify that you've exactly followed steps 1 to 3 on how to include the script, and everything mentioned under "Extended Configuration" further down this page.
c) Watch the JS Error Console of your browser. If there are errors, you can be sure that either the script hasn't been included correctly, or that there are syntax or logical errors in your own JS lines, or in some other script included into the page.
d) Please don't claim you've found a bug - unless you've checked everything very carefully, and you're absolutely sure. Please understand that I like developing code much more than debugging other peoples' web pages. Feedback is welcome, of course!

 
 
 
 
Extended Configuration

5. Alternative: Convert HTML element to tooltip
Instead of defining the tooltip text directly, you can specify an arbitrary HTML element to be converted to a tooltip. This is advantageous in some aspects:
  • You can have really important stuff in tooltips, since HTML content (unlike JavaScript content) of a page is relevant to web search engines.
  • If placed conveniently in the page, the content is also available for users who have disabled JavaScript.
  • Optionally, the HTML element can even stay visible; for example, if you want to display its content in a tooltip at a different location.
  • It may be easier to define complex inner tooltip HTML directly in the HTML element to be converted, rather than in a JavaScript string.

To define a tooltip to be created from an HTML element, just pass the ID of the desired HTML tag to the function TagToTip(). Example:

<a href="index.htm" onmouseover="TagToTip('Span2')" onmouseout="UnTip()">Home page </a>
...
<span id="Span2">This is some comment<br>about my home page</span>
...

In this example, the tooltip over the link will display the content grabbed from the <span> element. Note that only the inner content including the linebreak tag will be copied, whilst the SPAN tag itself and any formatting applied to it will not be inherited.
 
While the page is loading, the Tooltip Library hides automatically HTML elements to be converted to tooltips (e.g. the <span> element in the example above). To disable this auto-hide feature, set the variable TagsToTip in the global tooltip configuration in wz_tooltip.js to the value false (preset default: true). If desired, you must hide those HTML elements yourself, by setting their CSS 'display' property to 'none'.
 
As a side note: Especially in IE, page loading performance might benefit from disabling the auto-hide feature.
DHTML: Tooltips per JavaScript  
Top of page
 
Features
 
Cross Browser
 
Documentation
 
Extensions
 
Download
 
 
 
6. HTML inside tooltips

For images inside the tooltip, the width and height attributes in the <img> tags must be specified. This enables the script to determine the tooltip size correctly.
 
Doublequotes within the tooltip text must be written as HTML character entity (&quot;), since doublequotes serve already as delimiters for the onmouseover eventhandler, and cannot be nested. Apostrophes (singlequotes) must be masked with a preceding backslash, since apostophes serve already as delimiters for the tooltip text. As delimiters for HTML tag attributes inside the tooltip text, you can use either &quot; or \' . Example:
Correct:
<a href="index.htm" onmouseover="Tip('Text with <img src=\'pics/image.jpg\' width=\'60\'>image.')" onmouseout="UnTip()"> Homepage </a>
or
<a href="index.htm" onmouseover="Tip('Text with <img src=&quot;pics/image.jpg&quot; width=&quot;60&quot;>image.')" onmouseout="UnTip()"> Homepage </a>
 
Wrong:
<a href="index.htm" onmouseover="Tip('Text with <img src="pics/image.jpg" width="60">image.')" onmouseout="UnTip()"> Homepage </a>

 
 
7. Formatting tooltips with CSS classes

Simply wrap the tooltip text in a DIV or SPAN element of the desired CSS class. You can do the same with the title text (for how to define a tooltip title, see the description of the TITLE command in the commands reference below). Example:
... onmouseover="Tip('<div class=&quot;TipCls1&quot;>Text of tooltip number one</div>')" ...
... onmouseover="Tip('<span class=\'TipCls2\'>Text of tooltip number two</span>')" ...
... onmouseover="Tip('Tooltip number 3', TITLE, '<div class=\'TitleCls\'>Some Title</div>')" ...

 
 
8. Tooltip content via variable or function call

Instead of a string enclosed with single quotes, Tip() accepts as well a variable or a call to a function defined elsewhere, for instance in a <script> block or in a separate JS file. The same is true for commands passed to Tip() or TagToTip() (listing and description of commands see below). Thus, each time a tooltip is about to be displayed, its content and formatting could be established dynamically.
Example:
<html>
<head>
...
<script type="text/javascript">
var txt1 = "This is the text of the first tooltip";

function TooltipTxt(n)
{
    return "This is the text of the " + n + " tooltip";
}

</script>
</head>
<body>
<script type="text/javascript" src="wz_tooltip.js"></script>
...
<a href="a.htm" onmouseover="Tip(txt1)" onmouseout="UnTip()">Link 1</a>
...
<a href="b.htm" onmouseover="Tip(TooltipTxt('second'))" onmouseout="UnTip()">Link 2</a>
...
<a href="c.htm" onmouseover="Tip(TooltipTxt('third'))" onmouseout="UnTip()">Link 3</a>
...
</body>
</html>
DHTML: Tooltips per JavaScript  
Top of page
 
Features
 
Cross Browser
 
Documentation
 
Extensions
 
Download
 
 
 
9. Commands to customize tooltips individually

The global default configuration, taking effect on all tooltips, can be changed in the JavaScript file itself, in the section "GLOBAL TOOLTIP CONFIGURATION". To configure tooltips individually, you can use the commands listed below. These individual commands override the global configuration in wz_tooltip.js. They can be passed to the Tip() or TagToTip() function calls in the onmouseover eventhandlers. Each command must be accompanied by the desired value, separated by a comma:
onmouseover="Tip('Some text', ABOVE, true)"
or
onmouseover="TagToTip('SomeID', TITLEFONTCOLOR, '#CCFFCC')"

Multiple commands form a comma-separated list of command-value pairs. Order of commands is arbitrary. Example:
onmouseover="Tip('Some tooltip text', SHADOW, true, TITLE, 'Some Title', PADDING, 9)"


Command Description
ABOVE Positions the tooltip above the mousepointer. Value: true or false.
 
Combine with OFFSETY to adjust the vertical distance from the mousepointer, or with CENTERMOUSE to center the tooltip horizontally above the mousepointer.
BGCOLOR Background color of the tooltip. Value: HTML color, in single quotes, e.g. '#D3E3F6' or 'DarkCyan', or empty string '' for no background.
Example:
onmouseover="Tip('Some text', BGCOLOR, '#D3E3F6')"
or
onmouseover="Tip('Some text', BGCOLOR, '')"
BGIMG Background image. Value: Path to image, in single quotes.
Example:
onmouseover="Tip('Some text', BGIMG, '../images/tipbackground.gif')"
BORDERCOLOR Border color. Value: HTML color, in single quotes, e.g. '#dd00aa'.
BORDERSTYLE Border style. Value: CSS border style, in single quotes. Recommend are 'solid' (default), 'dashed' or 'dotted', others may not work in all browsers.
BORDERWIDTH Width of tooltip border. Value: Integer ≥ 0. Default is 1. Use 0 for no border.
Example:
onmouseover="Tip('Some text', BORDERWIDTH, 2)"
CENTERMOUSE Centers the tooltip horizontally beneath (or above) the mousepointer. Value: true or false. Consider that the tooltip is offset from the center by the value globally set in wz_tooltip.js (config. OffsetX), or as specified by the OFFSETX command.
Example:
onmouseover="Tip('Some text', CENTERMOUSE, true, OFFSETX, 0)"
CLICKCLOSE Closes the tooltip once the user clicks somewhere inside the tooltip or into the document. Value: true, false.
CLICKSTICKY Enables the user to fixate the tooltip, by just clicking onto the HTML element (e.g. link) that triggered the tooltip. This might help the user to read the tooltip more conveniently. Value: true, false.
 
onmouseover="Tip('Text', CLICKSTICKY, true, CLICKCLOSE, true, CLOSEBTN, true)"
In this example, additionally specifying CLICKCLOSE enables the user to close the tooltip with just another click somewhere into the document. Redundantly provided is a closebutton.
CLOSEBTN Displays a closebutton in the titlebar. Value: true, false.
CLOSEBTNCOLORS Colors used for the closebutton.
 
Value must be a comma-separated array of 4 color values. Each color in single quotes. The entire array must be enclosed with a pair of square brackets, see example below, since it's actually a single parameter. The 4 colors have the following meanings:
1. Background color
2. Text color
3. Highlighted background, while the button is being hovered
4. Hilighted text color, while the button is being hovered
For each of these colors, you can also specify an empty string '', in which case the title background, or title text color, respectively, is used for that button state.
 
Example:
Tip('Text', CLOSEBTN, true, CLOSEBTNCOLORS, ['', '#66ff66', 'white', '#00cc00'], STICKY, true)
In this example, the first color value (background color) is an empty string. Therefore the closebutton inherits the titlebar background.
CLOSEBTNTEXT Text in the closebutton. Value must be enclosed with single quotes. Example:
Tip('Tooltip text', CLOSEBTN, true, CLOSEBTNTEXT, 'Click Me', STICKY, true)
Globally preset in wz_tooltip.js is '&nbsp;X&nbsp;' - the whitespace entities '&nbsp;' add some horizontal padding to the button.
COPYCONTENT COPYCONTENT has only effect on tooltips created with TagToTip(), that is, for HTML elements converted to tooltips.
Value: true, false.
If true (this is the default behaviour preset in wz_tooltip.js), just a copy of the text (or inner HTML) of the HTML element is inserted into the tooltip. If false, the entire HTML element (its DOM node) by itself is temporarily converted to a tooltip, which may be useful in the following aspects:
1.) If the HTML element converted to a tooltip contains a form with inputs, their current user input will be maintained even while the tooltip is not displayed.
2.) The tooltip inherits the style properties of the HTML element.
Example how to convert an HTML element entirely to a tooltip, by applying COPYCONTENT with the value false:
TagToTip('SomeID', COPYCONTENT, false, BORDERWIDTH, 0, PADDING, 0)
Moreover, this example turns off the native tooltip border (BORDERWIDTH, 0), and sets the native tooltip padding to zero, so only the padding and border defined for the HTML element itself are displayed.
DELAY Tooltip shows up after the specified timeout, in milliseconds. A behavior similar to OS based tooltips.
Value: Integer ≥ 0. Use 0 for no delay. In wz_tooltip.js preset and recommended is 400.
Example:
onmouseover="Tip('Some text', DELAY, 1000)"
DURATION Time span, in milliseconds, until the tooltip is hidden, even if the STICKY command has been applied, or even if the mouse is still on the HTML element that has triggered the tooltip.
Value: Integer. Use 0 for no limitation (this is the default).
 
A negative value has a different meaning: It specifies a duration, in milliseconds, starting with the onmouseout until the tooltip is hidden. In other words, a negative value makes tooltip hide with some delay, rather than immediately. Especially useful for tooltips that don't follow the movements of the mouse (FOLLOWMOUSE, false).
EXCLUSIVE No other tooltip can be displayed until this one has been closed actively by the user. Value: true, false. Makes only sense for sticky tooltips (STICKY command). Of course, you must also provide the CLOSEBTN or/and CLICKCLOSE command to give the user a means to close the tooltip.
FADEIN Fade-in animation. The value (integer ≥ 0) specifies the duration of the animation, in milliseconds. 0 for no animation.
 
Not supported in Opera prior to v.9.0, old versions of Safari, some versions of Konqueror. These fall back to normal, non-animated behaviour.
FADEOUT Fade-out animation. The value (integer ≥ 0) specifies the duration of the animation, in milliseconds. 0 for no animation. Recommended: combine with FADEIN. Note that a small animation duration of 100 ms (recommended) is globally preset in wz_tooltip.js.
 
Not supported in Opera prior to v.9.0, old versions of Safari, some versions of Konqueror. These fall back to normal, non-animated behaviour.
FIX
Mode 1: Fixed x and y coordinates.
Shows the tooltip at the fixed coordinates [x, y]. Value: Two comma-separated integers in square brackets.
Example:
onmouseover="Tip('Some text', FIX, [230, 874])"
You can also call function(s) defined elsewhere that calculate the coordinates dynamically:
onmouseover="Tip('Text', FIX, [CalcFixX(), CalcFixY()], BORDERWIDTH, 2)"
or
onmouseover="Tip('Text', FIX, CalcFixXY(), ABOVE, true)"
In the latter example, the function CalcFixXY() must return an array containing the two numbers.
FIX
Mode 2: Fixed position at a certain HTML element.
Displays the tooltip at any desired HTML element - optionally even a different one than Tip() is called from. Value: Three comma-separated values in square brackets. The first value specifies the HTML element to display the tooltip at, either by its ID (string, in single quotes), or by a direct reference (no quotes). The second and third value (integers) define the horizontal and vertical offset of the tooltip from the left-bottom corner of the HTML element.
 
Example 1, ID of HTML element:
... onmouseover="Tip('Some text', FIX, ['PurpleSpan', 0, 5])"
...
<span id="PurpleSpan">HTML element to show the tooltip on</span>
This code snippet lets the tooltip appear 5 pixels below the bottom edge of the SPAN element.
 
Example 2, direct reference to HTML element:
<a href="..." onmouseover="Tip('Some text', FIX, [this, 0, 5], ABOVE, true)" onmouseout="UnTip()">Link</a>
This code snippet displays the tooltip directly at the HTML element (link) hovered with the mouse. As reference, we use the JavaScript keyword this - which automatically points to the HTML element the JavaScript eventhandler (e.g. onmouseover) stands in. Additionally, the ABOVE command is used in order to place the tooltip at the top edge of the HTML element.
FOLLOWMOUSE The tooltip follows the movements of the mouse. Value: true, false. Default: true.
 
When turning this off by applying the value false, the tooltip behaves like OS-based tooltips, which usually don't follow the mouse.
FONTCOLOR Font color. Value: HTML color, in single quotes, e.g. '#990099'
FONTFACE Font face (font family).
Value: As you'd specify it in HTML or CSS, enclosed with single quotes, e.g. Tip('Some text', FONTFACE, 'Arial, Helvetica, sans-serif', FONTSIZE, '12pt')
FONTSIZE Font size. Value: Size with unit, in single quotes. Unit ('px', 'pt', 'em' etc.) is mandatory.
FONTWEIGHT Font weight. Value: 'normal' or 'bold', in single quotes.
HEIGHT Height of the tooltip body, without title, shadows etc.. Value: Any integer.
If 0 (the preset default), the height is automatically adapted to the content of the tooltip. A negative number (e.g. -100) specifies a maximum limit for the automatic adaption (in this example the height won't ever go beyond 100 pixels).
 
Note that the tooltips follow the W3C box model, which means that the specified height applies to the actual content of the tooltip only, excluding padding (see PADDING command), border and shadow. If the height of the tooltip content exceeds the specified height, the tooltip is featured with a vertical scrollbar. Therefore, make sure that such tooltips of limited height are sticky (see STICKY command), so your visitors are given the chance to scroll the tooltip content.
JUMPHORZ Value: true, false. Test again.
If true: When touching the window boundary, the tooltip jumps horizontally to the other side of the mouse.
If false (preset default in wz_tooltip.js): The tooltip just stops by the right (or left) window boundary. In either case, the tooltip is prevented from extending past the window boundary.
JUMPVERT When it touches the bottom (or top) window boundary, the tooltip jumps vertically to the other side of the mouse.
Value: true, false. This behaviour is on (true) by default (preset in wz_tooltip.js).
 
Important: At least either JUMPVERT or JUMPHORZ behaviour, or both, should be true, so the mouse cannot enter the tooltip and thus trigger an onmouseout event when the tooltip is simultaneously stopped by a vertical and horizontal window boundary. Recommended and preset in wz_tooltip.js: JUMPVERT true, JUMPHORZ false.
LEFT Tooltip positioned on the left side of the mousepointer. Value: true, false.
LEFT and ABOVE commands combined.
Example:
onmouseover="Tip('Some text', LEFT, true, ABOVE, true)"
OFFSETX Horizontal offset from mouse-pointer. Value: Any integer. May also be negative.
OFFSETY Vertical offset from the mouse-pointer. Value: Any integer. May also be negative.
OPACITY Transparency of tooltip. Value: Integer between 0 (fully transparent) and 100 (opaque, no transparency).
 
Opacity is the opposite of transparency, i.e.
opacity = 100 - transparency (in percent).
Another example with image (taken on my 9000-km / 5500-miles recumbent bicycle trip Hamburg-Northcape-Munich), shadow via SHADOW command, content centered using TEXTALIGN, background image via BGIMG and animation via FADEIN and FADEOUT commands.
 
Not supported in Opera prior to v.9.0, old versions of Safari and some versions of Konqueror.
PADDING Inner spacing of tooltip, between border and content. Value: Integer ≥ 0.
SHADOW Tooltip drops a shadow. Value: true, false
SHADOWCOLOR Shadow color. Value: HTML color, in single quotes.
Example:
onmouseover="Tip('Some text', SHADOW, true, SHADOWCOLOR, '#dd99aa')"
SHADOWWIDTH Shadow width (offset). Value: Integer ≥ 0.
Example:
onmouseover="Tip('Some text', SHADOW, true, SHADOWWIDTH, 7)"
STICKY The tooltip stays fixed at its initial position until another tooltip pops up. Value: true, false.
 
With DURATION you can enforce the tooltip to disappear after a certain time span.
TEXTALIGN Aligns the text in the body of the tooltip. Value: 'right', 'center', 'justify' or 'left'.
Example:
onmouseover="Tip('Some text', TEXTALIGN, 'right')"
TITLE Displays a titlebar. Value: Text to display, in single quotes. May even contain HTML, which gives you additional freedom in fashioning the titlebar.
TITLEALIGN Aligns the text in the titlebar. Value: 'right', 'center', 'justify' or 'left'
TITLEBGCOLOR Backgroundcolor of the titlebar. Value: HTML color, in single quotes. If it's an empty string '', the border color (see also BORDERCOLOR command) is used (this is the default).
TITLEFONTCOLOR Color of title text. Value: HTML color, in single quotes. If it's an empty string '', the backgroundcolor of the tooltip body (see also BGCOLOR command) is used (this is the default).
TITLEFONTFACE Font face for title text. Value: Like in HTML or CSS. Enclosed with single quotes. If the value is an empty string '', the tooltip body font, in boldified form, is used (this is the default).
Example:
onmouseover="Tip('Some text', TITLE, 'Some Title', TITLEFONTFACE, 'Verdana,sans-serif')"
TITLEFONTSIZE Font size of title text. Value: Size with unit, in single quotes. Unit ('px', 'pt', 'em' etc.) is mandatory. If the value is an empty string '', the fontsize of the tooltip body is applied.
TITLEPADDING Padding around the title. Value: Integer ≥ 0.
WIDTH Width of tooltip. Value: Any integer.
If 0 (the preset default), the width is automatically adapted to the content of the tooltip. A negative number (e.g. -240) specifies a maximum limit for the automatic adaption (in this example the width won't ever go wider than 240 pixels).
 
A value of -1 for WIDTH has a special meaning: In this case the width of the tooltip is determined by the extent of the title. That is, the tooltip will be as wide as the title plus, if specified, the closebutton.
 
Note that the tooltips follow the W3C box model, which means that the specified width applies to the actual content of the tooltip, excluding padding (see PADDING command), border and shadow.


 
 
 
Extensions

Visit the Extensions page for additional configuration options.
 
 
 
 
Download
wz_tooltip.js 5.31, published under the LGPL:
wz_tooltip.zip (16 KB)
 
history.htm (Changelog of wz_tooltip.js)
 
Important notes for users of previous versions
 
Starting with version 5.0, an onmouseout attribute is required for each HTML tag that has a tooltip. Example:
<a href="index.htm" onmouseover="Tip('Some text')" onmouseout="UnTip()"> Home </a>
Simply call UnTip() from inside those onmouseout attributes. See also documentation above. The additional onmouseout attribute may be a bit less elegant, but gives you more freedom in specifying the event upon which to hide a tooltip.

 
 
 
Old Version For those who are still using a version prior to v.4.0 and want to stay with the old rules of defining tooltips and including the script:
Documentation and download of wz_tooltip.js v.3.45
 
 
 
Donation
Financial support for the very numerous hours of development and for the costs of hosting this website is welcome.
Posted by 1010
반응형

[javascript] 입력 문자 한글 체크


function koreanCheck(str) {
    var i;
    var ch;
   
    for (i=0;i<str.length;i++) {
        ch = escape(str.charAt(i));        //ISO-Latin-1 문자셋으로 변경

        if (strCharByte(ch) != 2) { //한글이 아닐 경우
            return;
        }
    }
}

function strCharByte(chStr) {
    if (chStr.substring(0, 2) == '%u') {
        if (chStr.substring(2,4) == '00')
            return 1;
        else
            return 2;        //한글
    } else if (chStr.substring(0,1) == '%') {
        if (parseInt(chStr.substring(1,3), 16) > 127)
            return 2;        //한글
        else
            return 1;
    } else {
            return 1;
    }
}


출처 : http://ingenuity.egloos.com/2789643

Posted by 1010
반응형

function getParameter( name )
{
 name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");

 var regexS = "[\\?&]" + name + "=([^&#]*)";
 var regex = new RegExp( regexS );
 var results = regex.exec( window.location.href );

 if( results == null )
  return "";
 else
  return results[1];
}


출처 : http://www.netlobo.com/url_query_string_javascript.html

Posted by 1010
반응형
 

보통 브라우저명을 체크할 때 아래 코드를 많이 사용합니다.

var DOM = (document.getElementById) ? true : false; // W3C 표준
var IE4 = (!DOM && document.all) ? true : false; // IE4
var IE5 = (DOM && (navigator.userAgent.indexOf("MSIE")>-1)) ? true : false; // IE5 >= 5
var NS4 = (!DOM && document.layers) ? true : false; // NN4
var NS5 = (DOM && (navigator.userAgent.indexOf("Gecko")>-1)) ? true : false // NN5 >= 5

또는,
navigator.appName == "Microsoft Internet Explorer"
navigator.appName == "Netscape"

위처럼 하면 한 가지 문제가 생기는데 바로 NS와 FF 입니다.
알다시피 FF 도 모질라의 뿌리를 갖고 있으므로 Netscape 를 브라우저명에 같이 출력합니다.
그래서 위처럼 하게되면 근래들어 급속한 사용자증가를 보이고 있는 FF 를 제대로 가려낼 수가 없습니다.
또한 FF 는 왠만한 부분은 IE6과 비슷합니다.  하다못해 스크롤링 되는 레이어도 같은 코드로 지원합니다.  그러나 NS 는 분명히 다릅니다.  IE와 FF 에서 스크롤되는 레이어도(예를 들어 영카트1에 있는 오른쪽 움직이는 스크롤처럼) NS에서는 지원되지 않으며, 영카트의 스크롤 레이어가 브라우저명에서 NS 를 기준으로 체크하므로 FF에서는 스크롤이 움직이지 않습니다.

위와 같은 경우의 해결책이며..사실 해결책이라기 보다는 가장 정확한 브라우저명을 체크하는게 아닌가 싶습니다.

//브라우저 이름으로 브라우저 구분 : Netscape Firefox MSIE
if(new RegExp(/Firefox/).test(navigator.userAgent)){
    FF (파이어폭스)
}else if(new RegExp(/Netscape/).test(navigator.userAgent)){
    NS (넷스케이프)
}else if(new RegExp(/MSIE/).test(navigator.userAgent)){
  IE (익스플로러)
}

위와 같이 정확한 브라우저명을 체크할 수 있으며, 버젼까지 체크할 경우는
navigator.appVersion.indexOf 를 이용하여 정확히 체크할 수 있습니다.

 

=========================================================================

//브라우저 명

var user_app_name = "";

if(new RegExp(/Firefox/).test(navigator.userAgent)){
 user_app_name = "FF";
}else if(new RegExp(/Netscape/).test(navigator.userAgent)){
 user_app_name = "NS";
}else if(new RegExp(/MSIE/).test(navigator.userAgent)){
 user_app_name = "IE";
}else if(new RegExp(/Opera/).test(navigator.userAgent)){
 user_app_name = "OP";
}

 

머 이렇게 쓰면 될려나...ㅋㅋ

Posted by 1010
반응형
 \n만 치환하면 안된다 \r\n 전부다 해줘야 한다.--(이것 때문에 고생했슴)

1. textarea 에 엔터값을 그냥 DB에 넣어서 처리 할 경우

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

DB상에는 엔터값이 먹힌 상태로 들어간다. 그 값을 나중에 html 코드에 가져오면

그냥 한줄로 출력이 된다.

이 때 <pre>태그를 써서 줄바꿈이 먹게 만들면 될것이다.

하지만 잘 살펴보면 DB상에 저장된 데이터에서 맨 마지막에 엔터가 한번 더 들어가 있는 것을 볼 수 있을 것이다. 따라서 내가 원하는 이쁜 배열은 안나온다..


2. textarea에서 엔터값을 치환<권장하는 방법이다>

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

이 부분은 여러 문서가 있다. asp,php,jsp의 처리 방법이 같지 않은거 같다.

여기서 사용하는 함수는 replace 함수이다(함수에 대한 설명은 찾아보삼)

textarea의 name 값이 contents 라 한다면,

그 값을 받는 부분에서 변환을 한다.

(실질적인 JSP 코드가 들어가있는 부분을 말한다.)


String content = request.getParameter("contents");

 전페이지에서 DB쿼리 실행하는 페이지에서 쓴다.

이 부분을 통해 textarea 값을 받아올 수 있따.

textarea 상에서 엔터는 어떤문자로 인식이 되냐면

\r\n 으로 표시가 된다.

이것을 치환을 한다!


contents = contents.replace("\r\n","<br>");

이렇게 하면 엔터가 DB상에 <br>로 바껴서 저장이 되고, html 코드에 가져올 때 자동적으로 <br>태그가 먹혀서 줄바꿈이 된다.


이 방법을 쓴다면, 이 값을 불러오는 페이지에서 아무 처리를 안해도 원하는 결과를

얻을 수 있다

Posted by 1010
반응형
각각의 다운로드 버튼을 클릭하셔서 받으시던지 모두 받으시려면 제일 하단의 "모두 다운로드" 이용하세요.
gBtn1 다운로드 (DOWN)
gBtn2 다운로드 (DOWN)
gBtn3 다운로드 (DOWN)
gBtn4 다운로드 (DOWN)
gBtn5 다운로드 (DOWN)
gBtn6 다운로드 (DOWN)
gBtn7 다운로드 (DOWN)
gBtn8 다운로드 (DOWN)
gBtn9 다운로드 (DOWN)
gBtn10 다운로드 (DOWN)
gBtn11 다운로드 (DOWN)
gBtn12 다운로드 (DOWN)
gBtn13 다운로드 (DOWN)
gBtn14 다운로드 (DOWN)
gBtn15 다운로드 (DOWN)
gBtn16 다운로드 (DOWN)
gBtn17 다운로드 (DOWN)
gBtn18 다운로드 (DOWN)
gBtn19 다운로드 (DOWN)
gBtn20 다운로드 (DOWN)
gBtn21 다운로드 (DOWN)
모두 다운로드 (DOWNLOAD ALL)
출처 : http://poshopzil.com
Posted by 1010
반응형
출처 : http://www.ihelpers.co.kr
원저자 : 손상모

앞에서 배운 지식을 바탕으로 간단한 RSS Reader를 제작해 보도록 하겠습니다. 먼저 아래의 데모를 한번씩들 실행하여 보시기 바랍니다. 그리고 구독하고 있는 채널이 있다면 다른 RSS URL로 테스트도 해 보시구요. 아마도 해당 강좌를 보신 후에는 이 보다 멋진 RSS Reader(Aggregator)를 작성하실 수 있을 것입니다.

1. 데모보기

Simple RSS Reader - http://www.ihelpers.co.kr/lib/jmrss/simplereader.php?URL=http://rss.joins.com/joins_news_list.xml

2. URL 통신
저번 시간에는 RSS 파싱하는 방법에 대하여 소개를 하였습니다. 이번에는 RSS Reader 구현을 위한 URL 통신 방법과 그외의 핵심 기능에 대하여 알아보도록 하겠습니다.

그럼 URL로 RSS 구문을 어떻게 가지고 올까요?

저의 경우는 대부분의 경우는 HTTP 모듈을 사용하나, PHP에서는 fopen 함수를 사용하여 복잡한 과정 없이 웹상의 정보를 로컬디렉토리의 파일정보 처리하는 것 처럼 너무도 쉽게 구현 할수  있습니다.

HTTP의 헤더정보를 같이 좀더 세부적인 처리를 원하는 분은 소스코드에 포함된 "httpclass.php" 클래스를 분석해 보시기 바랍니다. 해당 강좌의 모든 코드는 HTTP 모듈을 사용하였습니다.

//$fd = fopen("http://www.ihelpers.co.kr", "r");
$fd = fopen("http://xmlmanager.egloos.com", "r");
while (!feof($fd)) {
$buffer .= fgets($fd, 4086);
}
fclose($fd);
echo $buffer;
?>
3. RSSReader Class
RSSReader 클래스는 RSSParser 클래스,URLCache 클래스,httpclass 클래스 사용하며, 특히 RSSParser 클래스를 상속받아 사용하고 있습니다. 클래스를 만들면서도 상속에 대한 문제점으로 사용여부를 두고 갈등을 했었지만, RSSParser에 포함된 GET 함수들을 모두 다시 작성할 생각을 하니 너무 귀찮아서 PHP에서 처음으로 상속을 사용해 보았습니다. 혹시 아직도 PHP에서 Class 나 상속기능을 사용해 보지 않으신 분은 참고하여 보시면 일정 부분 도움이 될것입니다.

RSSReader 변수(Property)

  • url - RSS URL정보
  • isCache - Cache 사용여부 ( true,false )
  • CacheDir - Cache 디렉토리
  • cacheInterval - Cache 갱신 주기
  • ErrNum - 에러번호
  • ErrMsg - 에러메세지
RSSReader 함수(method)
  • RSSReader - 생성자로써 URL정보,Cache사용여부,Cache 갱신주기, Cache 디렉토리를 변수로써 입력 받는다.
  • setCache - Cache 사용여부 설정
  • setCacheDir - Cache 디렉토리 설정
  • setCacheInterval - Cache 갱신 주기 설정
  • Read

    RSS Reader 클래스에서 가장 주요 업무인 HTTP 통신과 RSS 구문 분석을 수행하는 함수이니 RSSReader 클래스에서 가장 중요한 함수라고 할 수 있을 것입니다. Read 함수는 내부적으로 _getResponse를 호출하여 HTTP 통신을 수행하고, 부모 클래스의 parse 함수를 통하여 RSS 구문을 분석하여 줍니다.

  • _getResponse

    Cache 사용여부를 판단하고 Cache를 사용할 경우는 Cache된 파일의 최종수정시간과 설정된 갱신 주기를 비교하여 Cache의 갱신 및 조회여부를 판단하여 URL정보를 읽어오게 됩니다. Cache를 사용하지 않을 경우는 당연히 직접 자료를 조회하게 됩니다.

    if($status == 0){ // 캐쉬정보가 이전것일때
    $response = $cache->get($this->url);
    $http->AddHeader("If-Modified-Since",$response['last-modified']);
    $http->AddHeader("ETag",$response['etag']);
    }
    $http->Get($path);


    if($http->Response['code'] == 304){
    } elseif($http->Response['code'] == 200 || $http->Response['code'] == 304){
    $response = $http->Response;
    $cache->set($this->url,$response);
    } else {
    $this->Error(0,"Response Not Success");
    return false;
    }
    return $response;
  • 위의 코드는 조금 재미있게 볼 수 있을 것 같습니다. Cache 정보가 이전 것이라면 URL통신을 하여 새로운 정보를 가지고 와야 할 것입니다. 그 때 etag 와 last-modified를 포함하여 웹서버와 통신하여 URL 정보가 Cache된 정보와 비교하여 갱신이 되지 않았다면,웹서버는 상태코드로 304 를 리턴해 줍니다. 웹서버에 정보가 갱신이 되지 않았다면 RSS Reader쪽은 Cache정보를 갱신할 필요가 없고 웹서버에서는 URL에 해당하는 문서의 갱신상태만 파악하면 되기 때문에 좀 더 빠르게 통신을 할 수 있게 됩니다.

/*///////////////////////////////////////////////////////////////

작성자  : 손상모<smson@ihelpers.co.kr>
최초작성일 : 2004.10.27

변경내용  :

 2006.05.30 - 302 Object Moved 문제점 처리
 2006.05.30 - encoding 문제점 처리

http://www.ihelpers.co.kr

/////////////////////////////////////////////////////////////////*/

require_once("RSSParser.php");
require_once("URLCache.php");
require_once("httpclass.php");

/**
* RSS Reader Class
*
* RSS Format 읽기 기능 ( URLCache와 httpclass 이용 )
*
* @author Sang Mo,Son <smson@ihelpers.co.kr>
* @version 0.9 beta
* @access  public
*/
class RSSReader extends RSSParser {

 var $url;

 var $ErrNum;
 var $ErrMsg;

 var $isCache;

 var $CacheDir;

 var $cacheInterval;
   
 /**
     * Constructor
     *
     * @access public
  * @param string url
  * @param boolean Cache 유무
  * @param int  Cache 유효시간
     * @return void
     */
 function RSSReader($url,$isCache = true,$cacheInterval = 3600,$CacheDir = "./cache"){
  $this->url = $url;
  $this->isCache = $isCache;
  $this->cacheInterval = $cacheInterval;
  $this->CacheDir = $CacheDir;
  parent::RSSParser();
 }

 /**
     * Cache 유무 설정
     *
     * @access public
  * @param boolean Cache 유무
     * @return void
     */
 function setCache($isCache){
  $this->isCache = $isCache;
 }

 /**
     * Cache 디렉토리 설정
     *
     * @access public
  * @param string Cache 디렉토리
     * @return void
     */
 function setCacheDir($CacheDir){
  $this->CacheDir = $CacheDir;
 }

 /**
     * Cache 유효시간 설정
     *
     * @access public
  * @param int  Cache 유효시간
     * @return void
     */
 function setCacheInterval($cacheInterval){
  $this->cacheInterval = $cacheInterval;
 }

 /**
     * RSS 읽기
     *
     * @access private
     * @return boolean
     */
 function Read(){
  $response = $this->_getResponse();
  if($response){
   if(preg_match("/<\?xml.+encoding=\"(.+)\".+\?>/i",$response['body'],$match)){
    if(strtoupper($match[1]) == "UTF-8"){
     $response['body'] = iconv("UTF-8","EUC-KR",$response['body']);
     $response['body'] = str_replace("utf-8", "EUC-KR", $response['body']);
    }
   }
//   echo $response['body'];
   $this->parse($response['body']);
   return true;
  } else {
   return false;
  }
 }

 /**
     * RSS의 URL 또는 Cache 정보
     *
     * @access private
     * @return array response array
     */
 function _getResponse(){

  $aurl = parse_url($this->url);
  $host = $aurl["host"];
  $port = $aurl["port"];
  $path = $aurl["path"];
  if(!empty($aurl["query"])){
   $path = sprintf("%s?%s",$path,$aurl["query"]);
  }
  if(empty($port)){ $port = 80; }
  if(empty($path)){ $path = "/"; }


  if($this->isCache){
   $cache = new URLCache();
   $cache->setInterval($this->cacheInterval);
   $cache->setCacheDir($this->CacheDir);

   $status = $cache->checkCache($this->url);

   if($status == 1){     // 캐쉬정보가 새로운 것이라면
    $response = $cache->get($this->url);
    return $response;
   } else {
    $http = new HTTP($host,$port,10);
    if(!$http->Err){
     if($status == 0){   // 캐쉬정보가 이전것일때
      $response = $cache->get($this->url);
      $http->AddHeader("If-Modified-Since",$response['last-modified']);
      $http->AddHeader("ETag",$response['etag']);
     }
     $http->Get($path);

     if($http->Response['code'] == 302){
      $this->url = $http->Response['location'];
      $response = $this->_getResponse();
      return $response;
     } else {
      if($http->Response['code'] == 304){
      } elseif($http->Response['code'] == 200 || $http->Response['code'] == 304){
       $response = $http->Response;
       $cache->set($this->url,$response);
      } else {
       $this->Error(0,"Response Not Success");
       return false;
      }
      return $response;
     }
    } else {
     $this->Error(0,"Socket Connect Fail");
     return false;
    }
    $http->Close();
   }
  } else {

   $http = new HTTP($host,$port,10);
   if(!$http->Err){
    $buf = $http->Get($path);

    if($http->Response['code'] == 302){
     $this->url = $http->Response['location'];
     $response = $this->_getResponse();
     return $response;
    } else {
     if($http->Response['code'] == 200 || $http->Response['code'] == 304){
      return $http->Response;
     } else {
      $this->Error(0,"Response Not Success");
      return false;
     }
    }
   } else {
    $this->Error(0,"Socket Connect Fail");
    return false;
   }
   $http->Close();
  }
 }

    /**
     * 에러
     *
     * @access public
  * @param int  error number
  * @param string error message
     * @return void
     */
 function Error($errnum,$errmsg){
  $this->ErrNum = $errnum;
  $this->ErrMsg = $errmsg;
 }
}

4. URLCache에 대하여

브라우저가 Cache를 사용하지 않아 매번 접속시마다 변경이 잘 되지 않는 이미지를 다운로드 받아야 한다면 이처럼 웹이 발전되지 않았을 것입니다.

아마도 제작한 RSS Reader에서 Cache를 사용하지 않는다면, 채널을 구독하고 있는 사용자들의 주기적인 접속은 웹서버에 대한 공격으로 변신하여 웹서버 관리자의 얼굴을 하얗게 변하게 할 것입니다. 10,000명의 구독자에 의하여 프로그램이 1분 단위로 채널에 접속하여 정보의 갱신여부만 확인한다고 생각하면 이 만큼의 시스템 자원 낭비가 어디 있겠습니까?

RSS Reader의 경우는 시간이 많이 소요되는 Network 통신을 해야 하기에, 이 문제를 최소화 할 수 있는 Cache의 사용은 RSS Reader 프로그램 개발시에 상당히 중요한 부분이라고 생각합니다. Cache 사용은 "URL Cache를 사용하여 웹을 더욱 빠르게"  강좌와 소스코드에 포함되어 있는 URLCache 클래스를 참고하여 주십시요.

5. Simple RSS Reader

강좌 시작에서 본 간단한 RSS Reader 코드입니다.


include "RSSReader.php";
$url = $_GET["URL"];
$rss = new RSSReader($url,false);
echo "
echo "< style>\n?;
echo " echo " echo "
if(!empty($url)){
$response = $rss->Read();
if($response){
 $channel = $rss->getChannel();
 while (list($key, $value) = each ($channel)) {
  echo "\n?;
 }
  echo "
  $count = 0;
 foreach($rss->getItems() as $items){

  if($count == 0){
   $titles = $items;
   echo "    while (list($key, $value) = each ($titles)) {
    printf("
    }
    echo "    }
   echo "
   while (list($key, $value) = each ($items)) {
   printf("
   }
   echo "
   $count++;
  }
  echo "  }
}
echo "\n?;
?>

[ simplereader.php ]

6. 소스코드
Posted by 1010
반응형
function number_format(str){
        str = ""+str+"";
        var retValue = "";
        for(i=0; i<str.length; i++){
            if(i > 0 && (i%3)==0) {
                retValue = str.charAt(str.length - i -1) + "," + retValue;
            } else {
                retValue = str.charAt(str.length - i -1) + retValue;
            }
        }
        return retValue;
}
Posted by 1010
반응형

//var    _intValue   = '0123456789';
//var    _upperValue = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
//var    _lowerValue = 'abcdefghijklmnopqrstuvwxyz';
//var    _etcValue   = '~`!@#$%%^&*()-_=+\|[{]};:\'\",<.>/?';
//var    dayOfMonth = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

n = (document.layers) ? 1:0;
ie = (document.all) ? 1:0;
if (n) document.captureEvents(Event.KEYPRESS);

function fnTest(pval) {
  fnTest =  doReverse(pval.value) ;
  alert (fnTest);
}

// -------------------------------------------------------------------
// Function name: isInt
// Description  : 숫자인가를 체크하는 함수
// Parameter    : value(체크대상 문자)
// -------------------------------------------------------------------
// Usage        : var a='3'; if(isInt(a)) { alert("숫자입니다"); }
// -------------------------------------------------------------------
function isInt(value) {
 var _intValue   = '0123456789';
    var j;
    for(j=0;j<_intValue.length;j++)
      if(value == _intValue.charAt(j)) {
    return true;
 }
    return false;
}

// --------------------------------------------------------------------
// Function name: isNumeric
// Description  : 숫자로만 구성되어 있는지를 검사
// Parameter    : obj(화면컨트롤)
// --------------------------------------------------------------------
// Usage        : <input type="text" onBlur="isNumeric(this)">
// Caution      : 화면컨트롤에 데이타가 없는 경우에는 false를 리턴
// --------------------------------------------------------------------
function isNumeric(obj) {
 var str=obj.value;
 if (str.length == 0)
 return false;
 for (var i = 0; i < str.length; i++){
 var ch = str.substring(i, i + 1);
 if ((ch < "0" || "9" < ch) ){
     obj.focus();
     obj.select();  
   return false;
  }
 }
 return true;
}

// ---------------------------------------------------------------------
// Function name : isNumber(str)
// Description   : 숫자로만 구성되어 있는지를 검사, 숫자이면 return true
// Parameter     : str(측정대상값)
// ----------------------------------------------------------------------
// Usage         : if(isNumber(str)) { alert("숫자입니다.."); },
// Caution       : isNumeric(obj)과 다른점은 obj가 아닌 value값 사용
// ----------------------------------------------------------------------
function isNumber(value) {
 var result = true;
 for(j = 0; result && (j < value.length); j++) {
  if((value.substring(j, j+1) < "0") || (value.substring(j, j+1) > "9")) {
   result = false;
  }
 }
 return result;
}

// ---------------------------------------------------------------------
// Function name: getNumOnly
// Description  : 숫자와 문자열이 혼합되어 있는 것에서 숫자만 리턴
// Parameter    : obj(검사대상 문자열)
// ---------------------------------------------------------------------
// Usage        : <input type="text" onBlur="getNumOnly(this);">
//                검사대상 문자열이 '1134sd3dkk8'일 경우 '113438'만 리턴
// ---------------------------------------------------------------------
function getNumOnly(obj) {
 var strNew = "";
  var chkstr = "0123456789";
 var str = obj.value;
 for (var i = 0; i < str.length; i++) {
   if (chkstr.indexOf(str.substring(i, i + 1)) >= 0) {
     strNew += str.substring(i, i + 1);
   }
 }
  return strNew;
}

// ---------------------------------------------------------------
// Function name : isFloat(str)
// Description   : 숫자값인지 체크, '.' 포함
// Parameter     : str(측정대상값)
// ---------------------------------------------------------------
// Usage         : if(isFloat(str)) { alert("Float값입니다."); }
// ---------------------------------------------------------------
function isFloat(value) {
 var count = 0;
 var ch;
 
 for(i=0; i<value.length; i++) {
  ch = value.charAt(i);
 
  if(isNaN(ch)) {
   if(ch == ".") {
    count++;
   } else {
    return false;
   }
  }    
 }
 
 if(count > 1) {
  return false;
 } else {
  return true;
 }
 
 return result;
}

// -------------------------------------------------------------------
// Function name : getOnlyNumberKey()
// Description   : 키보드 입력시 숫자만 입력 가능
// Parameter     :
// -------------------------------------------------------------------
// Usage         : onKeyDown=getOnlyNumberKey()
// -------------------------------------------------------------------
function getOnlyNumberKey() {
 if ((event.keyCode >=48 && event.keyCode <=57)   // 자판 0~9
  || (event.keyCode >=96 && event.keyCode <= 105)  // keypad 0~9
  || (event.keyCode == 109)             // 자판 -
  || (event.keyCode == 189)             // keypad -
  || (event.keyCode == 8)              // back space
  || (event.keyCode == 9)              // tab
  || (event.keyCode == 13)             // enter
  || (event.keyCode == 46)             // delete
  || (event.keyCode >= 37 && event.keyCode <= 40)) // 방향키
 {
  return true;
 } else {
  event.returnValue = false;
 }
}

// ---------------------------------------------------------------------
// Function name : getNumberNCommaKey() 
// Description   : 키보드 입력시 숫자 및 ','가 입력 가능
// Parameter     :
// ---------------------------------------------------------------------
// Usage         : onKeyDown=getNumberNCommaKey() 
// ---------------------------------------------------------------------
function getNumberNCommaKey() {
 if ((event.keyCode >=48 && event.keyCode <=57)   // 자판 0~9
  || (event.keyCode >=96 && event.keyCode <= 105)  // keypad 0~9
  || (event.keyCode == 109)             // 자판 -
  || (event.keyCode == 189)             // keypad -
  || (event.keyCode == 188)             // 자판 ,
  || (event.keyCode == 8)              // back space
  || (event.keyCode == 9)              // tab
  || (event.keyCode == 13)             // enter
  || (event.keyCode == 46)             // delete
  || (event.keyCode >= 37 && event.keyCode <= 40)) // 방향키
 {
  return true;
 } else {
  event.returnValue = false;
 }

}

// ----------------------------------------------------------------------
// Function name : getNumberNDotKey()
// Description   : 키보드 입력시 숫자 및 '.'가 입력 가능
// Parameter     :
// ----------------------------------------------------------------------
// Usage         : onKeyDown=getNumberNDotKey()
// ----------------------------------------------------------------------
function getNumberNDotKey() {
 if ((event.keyCode >=48 && event.keyCode <=57)   // 자판 0~9
  || (event.keyCode >=96 && event.keyCode <= 105)  // keypad 0~9
  || (event.keyCode == 109)             // 자판 -
  || (event.keyCode == 189)             // keypad -
  || (event.keyCode == 110)             // 자판 .
  || (event.keyCode == 190)             // keypad .
  || (event.keyCode == 8)              // back space
  || (event.keyCode == 9)              // tab
  || (event.keyCode == 13)             // enter
  || (event.keyCode == 46)             // delete
  || (event.keyCode >= 37 && event.keyCode <= 40)) // 방향키
 {
  return true;
 } else {
  event.returnValue = false;
 }
}

// --------------------------------------------------------------------
// Function name : isDigitOrBar(str)
// Description   : '-' 기호를 포함한 숫자여부 판단, 숫자면 return true
// Parameter     : str(대상 문자열)
// --------------------------------------------------------------------
// Usage         : isDigitOrBar(str), 부호의 선행, 후행은 체크 못함
// --------------------------------------------------------------------
function isDigitOrBar(str) {
 for(var i=0; i < str.length; i++) {
  var ch= str.charAt(i) ;
  if((ch < "0" || ch > "9") && ch!="-") {
   return false;
  }
 }
 return true;
}

//---------------------------------------------------------------------
// Function name : getFormattedVal
// Description   : 숫자를 포멧이 갖추어진 문자열로 바꿈
//                 ###3 <= 숫자3은 세자리마다 ,를 찍겠다는 말
//                 .##### <= .(소수점)뒤로 5자리까지 표현하겠다는 말
// Parameter     : value  : 검사할 값
//                 format : 변환할 형태
// Return        :  변환된 값 리턴
// --------------------------------------------------------------------
// Usage         : getFormattedVal(value , "###3.#####")
//---------------------------------------------------------------------
function getFormattedVal(value,format) {
    value = ""+value;

    if(!format)
      return value;

    var sp = parseInt(format.charAt(3));

    if(!sp)
      return value;

    var pos = 0;
    var ret = "";
    var vSplit = value.split('.');
    var fSplit = format.split('.');
    var fp = fSplit[1];
    var fv = vSplit[1];
    var lv = vSplit[0];
    var len = lv.length;

    for(var i = len % sp; i < len; i += sp){
        if(i == 0 || lv.charAt(i-1) == '-')
            ret += lv.substring(pos,i);
        else
            ret += lv.substring(pos,i)+',';
        pos = i;
    }

    ret += lv.substring(pos,len);

    if(!fv)
        fv = "";
    if(!fp)
        fp = "";

    var len1 = fp.length;
    var len2 = fv.length;

    if(len1)
      ret += '.' + fv.substring(0,len1) + fp.substring(len1,len2);
    return ret;
}


//-------------------------------------------------------------------
// Function name : changeInt2Han
// Description   : 숫자 -> 한글로 변환
// Parameter     : string  : 변환 할 값
// Return        : 변환된 값 리턴 / 123 -> 일백이십삼
// -------------------------------------------------------------------
// Usage         : changeInt2Han(string)
//--------------------------------------------------------------------
function changeInt2Han(string) {
 hn = new Array("영","일","이","삼","사","오","육","칠","팔","구");
 hj = new Array("","만","억","조","경","해");
 ul = new Array("영천","영백","영십","영");
 tm = new Array();
 result = "";

 if (string.charAt(0)=="-") {
  result = "마이너스 ";
  string = string.substr(1,string.length-1);
 }

 loop_size = Math.ceil(string.length/4);
 string2 = "";

 for (count=string.length; count >= 0; count--)
  string2 += string.substring(count,count-1);
  string = string2;

 for (A=0;A<loop_size;A++) {
  sum = hj[A] + " ";
  tm[A] = string.substr(A*4,4);

  tm2 = "";
 
  for (count=tm[A].length; count >= 0; count--)
   tm2 += tm[A].substring(count,count-1);
 
  tm[A] = tm2;
  part_jari = tm[A].length;
 
  for (D=0;D<10;D++) {
   for (B=0;B<10;B++) tm[A] = tm[A].replace(B,hn[B]);
  }

    if (part_jari == 4) tm[A] = tm[A].charAt(0)+"천"+tm[A].charAt(1)+"백"+tm[A].charAt(2)+"십"+tm[A].charAt(3);
    else if (part_jari == 3) tm[A] = tm[A].charAt(0)+"백"+tm[A].charAt(1)+"십"+tm[A].charAt(2);
  else if (part_jari == 2) tm[A] = tm[A].charAt(0)+"십"+tm[A].charAt(1);
  else tm[A] = tm[A].charAt(0);

  for (C=0;C<4;C++) {
   if (tm[A].match(ul[C])) {
    part_jari--; tm[A] = tm[A].replace(ul[C],"");
   }
  }
   
  if (part_jari != 0) tm[A] += sum;
  }

 for (loop_size;loop_size>-1;loop_size--)
  result += tm[loop_size];
 
 result = result.replace("undefined","");
 return result;
}

//-----------------------------------------------------------------------
// Function name : changeInt2HanJa
// Description   : 숫자 -> 한자로 변환
// Parameter     : string  : 변환 할 값
// Return        : 변환된 값 리턴 / 일백이십삼 -> 壹百貳拾參
// ----------------------------------------------------------------------
// Usage         : changeInt2HanJa(string)
//-----------------------------------------------------------------------
function changeInt2HanJa(string) {
 hn = new Array("영","壹","貳","參","四","五","六","七","八","九");
 hj = new Array("","萬","億","兆");
 ul = new Array("영千","영百","영拾","영");
 tm = new Array();
 result = "";

 if (string.charAt(0)=="-") {
  result = "마이너스 ";
  string = string.substr(1,string.length-1);
 }
 loop_size = Math.ceil(string.length/4);
      string2 = "";
 for (count=string.length; count >= 0; count--)
  string2 += string.substring(count,count-1);
   
 string = string2;
 
 for (A=0;A<loop_size;A++) {
  sum = hj[A] + " ";
  tm[A] = string.substr(A*4,4);

  tm2 = "";

  for (count=tm[A].length; count >= 0; count--)
   tm2 += tm[A].substring(count,count-1);
 
  tm[A] = tm2;
  part_jari = tm[A].length;
  for (D=0;D<10;D++) {
   for (B=0;B<10;B++) tm[A] = tm[A].replace(B,hn[B]);
  }

  if (part_jari == 4) tm[A] = tm[A].charAt(0)+"千"+tm[A].charAt(1)+"百"+tm[A].charAt(2)+"拾"+tm[A].charAt(3);
  else if (part_jari == 3) tm[A] = tm[A].charAt(0)+"百"+tm[A].charAt(1)+"拾"+tm[A].charAt(2);
  else if (part_jari == 2) tm[A] = tm[A].charAt(0)+"拾"+tm[A].charAt(1);
  else tm[A] = tm[A].charAt(0);
  for (C=0;C<4;C++) {
   if (tm[A].match(ul[C])) {
    part_jari--; tm[A] = tm[A].replace(ul[C],"");
   }
  }
  if (part_jari != 0) tm[A] += sum;
 }

 for (loop_size;loop_size>-1;loop_size--) result += tm[loop_size];
   result = result.replace("undefined","");

 return result;
}

//-----------------------------------------------------------------------------
// Function name : isFraction
// Description   : 입력된 문자가 숫자, 분수(1/3,2/5..)인가를 체크하는 함수
// Parameter     : obj(입력 컨트롤명)
// ----------------------------------------------------------------------------
// Usage         : 사용자가 텍스트박스에 숫자값으로만 입력되어야 할 경우 이를
//                 검증하기 위해서 아래와 같이 사용
//                 <input type="text" onBlur="isFraction(this)">
//-----------------------------------------------------------------------------
function isFraction(obj) {
 var i,j;
 var str = new String(obj.value);
 var check_slash = 0;

 if ((str == '')||(str.length == 0))
   return true;

 for(i=0;i< str.length;i++) {
  if(!isInt(str.charAt(i))) {
 
   if(str.charAt(i) != '/') {
    alert('정수 또는 분수만 입력가능합니다.');
    obj.focus();
    obj.select();
    return false;
    } else {
    check_slash++;
    if (i==0) {
     alert('정수 또는 분수만 입력가능합니다.');
     obj.focus();
     obj.select();
     return false;
    }
   }
  }
 }
 j = i -1;

 if (str.charAt(j) == '/' || check_slash > 1) {
  alert('정수 또는 분수만 입력가능합니다.');
  obj.focus();
  return false;
 }
 return true;
}

//---------------------------------------------------------------------------------------
// Function name : checkDigitBody2
// Description   : 숫자 혹은 구분자('-', '.' 등)로만 구성되어 있는지를 검사
// Parameter     : obj(화면컨트롤), sep(구분자)
// --------------------------------------------------------------------------------------
// Usage         : <input type="text" onBlur="checkDigitBody2(this, '-')">
// Caution       : 화면컨트롤에 데이타가 없는 경우에는 false를 리턴
// --------------------------------------------------------------------------------------
function checkDigitBody2(obj, sep) {
 var str=obj.value;
 if (str.length == 0)
  return false;
 for (var i = 0; i < str.length; i++) {
  var ch = str.substring(i, i + 1);
  if ((ch < "0" || "9" < ch)) {
   if (ch != sep)
    return false;
  }
 }
 return true;
}

//---------------------------------------------------------------------------------------
// Function name : getNumberOnly
// Description   : 실수,정수,금액 유효성 체크 및 허용하지 않는 문자는 경고 없이 자동 삭제
// Parameter     : 필수 : obj(입력 컨트롤명), cmd(숫자 유형)
//---------------------------------------------------------------------------------------
// Usage         : <input name="num1" type="text"  onkeyup= "getNumberOnly(this, 'money')"  ...>
// Caution       : 일반적으로 다른 function에서 내부적 호출로 쓰임
//---------------------------------------------------------------------------------------
function getNumberOnly(obj, cmd) {
 var instr = obj.value;
 var cstr = "";
 var tempstr = "";

 if(cmd == "real") {
  cstr = "0123456789.-";          //실수
 } else if(cmd == "real2") {
  cstr = "0123456789.";      //양의실수
 } else if(cmd=="int") {
  cstr="0123456789-";             //정수
 } else if(cmd=="money") {
  cstr="0123456789,";       //금액
 } else if(cmd == "real3") {
  cstr = "0123456789.-,";         //실수 : , 포함
 } else if(cmd=='numeric') {
  cstr = "0123456789";      //숫자
 }

 //거꾸로 돌려야 함
 if(instr.length) {
  var len = instr.length;
  for(var i=len-1; i>=0; i--) {
   if(cstr.lastIndexOf(instr.charAt(i)) == -1) {
    instr = instr.substring(0, i)+ instr.substring(i+1);
    obj.value = instr;
   }
  }
 }
}

// --------------------------------------------------------------------------------------------
// Function name : addCommaStr
// Description   : 입력창에 숫자 데이터를 입력할때 자동으로 3자리별로 ',' 가 붙어 입력되게함
// Parameter     : str(문자열(숫자))
// --------------------------------------------------------------------------------------------
// Usage         :
// Caution       : 이 함수를 사용할때 Input 박스 값이 숫자 값인지 체크할 때는 쉼표를 자동으로
//                 체크하여 숫자여부를 판단하는 checkDigitBody2(obj, ",")를 사용한다.
// --------------------------------------------------------------------------------------------
function addCommaStr(str) {
 if (str.length < 1) {
    return "";
  } else {
  var tm = "";
  var ck = "";
  if (str.substring(0, 1) == "-") { //음수
   tm = str.substring(1, str.length);
   ck = "Y";
  } else {//양수
   tm = str;
   ck = "N";
  }
  var st = "";
  var cm = ",";

  for (var i = tm.length, j = 0; i > 0; i--, j++) {
   if ((j % 3) == 2) {
    if (tm.length == j + 1) st = tm.substring(i - 1, i) + st;
    else st = cm + tm.substring(i - 1, i) + st;
   } else {
    st = tm.substring(i - 1, i) + st;
   }
  }
  if (ck == "Y") st = "-" + st;
 }
 return st;
}

// --------------------------------------------------------------------------------------------
// Function name : delCommaStr
// Description   : 화폐구분자로 사용되는 ','문자를 제거하는 함수.
//                 보통 화면에는 ,로 표시하고, DB에는 ','를 제외한 숫자만을 insert할 때 사용
// Parameter     : str(금액형태의 문자열)
// --------------------------------------------------------------------------------------------
// Usage         :
// --------------------------------------------------------------------------------------------
function delCommaStr(str) {
 if (str.length < 1) {
  return "";
 } else {
  var st = "";
  var sp = ",";
  for (var i = 0; i < str.length; i++) {
   if (sp.indexOf(str.substring(i, i + 1)) == -1) {
    st += str.substring(i, i + 1);
   }
  }
  return st;
 }
}

// --------------------------------------------------------------------------------------------
// Function name : delComma
// Description   : 화폐구분자로 사용되는 ','문자를 제거하는 함수.
//                 보통 화면에는 ,로 표시하고, DB에는 ','를 제외한 숫자만을 insert할 때 사용
// Parameter     : obj(화면 입력박스명)
// --------------------------------------------------------------------------------------------
// Usage         :
// Caution       : delCommaStr 과 다른점은 value 가 아닌 obj값 사용
// --------------------------------------------------------------------------------------------
function delComma(obj) {
 var str =  String(obj.value);
 if (str.length < 1) {
  return "";
 } else {
  var st = "";
  var sp = ",";
  for (var i = 0; i < str.length; i++) {
    if (sp.indexOf(str.substring(i, i + 1)) == -1) {
      st += str.substring(i, i + 1);
    }
  }
  return st;
 }
}

// --------------------------------------------------------------------------------------------
// Function name : isUpperChar
// Description   : 영문 대문자인지를 체크하는 함수
// Parameter     : value(체크대상 문자)
// --------------------------------------------------------------------------------------------
// Usage         : var a='A'; if(isUpperChar(a)) { alert("대문자입니다"); }
// --------------------------------------------------------------------------------------------
function isUpperChar(value) {
 var _upperValue = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
 var i;
 for(i=0;i<_upperValue.length;i++)
  if(value == _upperValue.charAt(i)) {
   return true;
  }

 return false;
}

// --------------------------------------------------------------------------------------------
// Function name : isLowerChar
// Description   : 영문 소문자인지를 체크하는 함수
// Parameter     : value(체크대상 문자)
// --------------------------------------------------------------------------------------------
// Usage         : var a='k'; if(isLowerChar(a)) { alert("소문자입니다"); }
// --------------------------------------------------------------------------------------------
function isLowerChar(value) {
 var _lowerValue = 'abcdefghijklmnopqrstuvwxyz';
 var i;
 for(i=0;i<_lowerValue.length;i++)
  if(value == _lowerValue.charAt(i)) {
   return true;
  }

 return false;
}

// -------------------------------------------------------------------------------------------------
// Function name : 특수문자여부체크
// Description   : 특수문자인지를 체크하는 함수(영문이나 한글이 아닌)
// Parameter     : value(체크대상 문자)
// -------------------------------------------------------------------------------------------------
// Usage         : var a='&'; if(isEtcChar(a)) { alert("특수문자입니다"); }
// -------------------------------------------------------------------------------------------------
function isEtcChar(value) {
 var _etcValue   = '~`!@#$%%^&*()-_=+\|[{]};:\'\",<.>/?';
    var j;
    for(j=0;j<_etcValue.length;j++)
        if(value == _etcValue.charAt(j)) {
            return true;
        }
    return false;
}


// -------------------------------------------------------------------------------------------------
// Function name : isEtcChar(value)
// Description   : 특수문자인지를 체크하는 함수(영문이나 한글이 아닌)
// Parameter     : value(체크대상 문자), 문자열이 아님 char하나에 대한 체크가능
// -------------------------------------------------------------------------------------------------
// Usage         : var a='&'; if(cmm_is_etc_char(a)) { alert("특수문자입니다"); }
// -------------------------------------------------------------------------------------------------
function isEtcString(value) {
 var _etcValue   = '~`!@#$%%^&*()-_=+\|[{]};:\'\",<.>/?';
 var i,j;
 for(i=0;i<value.length;i++) {
  for(j=0;j<_etcValue.length;j++)
   if(value.charAt(i) == _etcValue.charAt(j)) {
    return true;
   }
 }
 return false;
}

// -------------------------------------------------------------------------------------------------
// Function name : 영문대문자 변환
// Description   : 영문대문자로 변환하는 함수
// Parameter     : obj(변환대상 문자열을 가지고 있는 화면 컨트롤오브젝트) cmm_to_upper
// -------------------------------------------------------------------------------------------------
// Usage         : 사용자가 소문자로 입력하더라도 DB에는 대문자로 입력하고자 하는 경우
// -------------------------------------------------------------------------------------------------
function getUpperStr(obj) {
  var strNew = '';
 var str = obj.value;
    for(i=0 ; i<str.length; i++ ) {
   if(str.charAt(i) >= 'a' && str.charAt(i) <= 'z')
    strNew += str.charAt(i).toUpperCase() ;
   else
    strNew +=  str.charAt(i);
    }
 
 obj.value = strNew;
}

// 사용빈도 : 중
// 함수명: 몇개의 정해진 문자만 입력가능하도록 검사하는 함수
// 설  명: 정해진 문자열(영문자, 공백, '-', ',')만 입력하는 지를 검사하는 함수
// 인  자: ctl_digit(화면컨트롤)
// --------------------------------------------------------------------------------------------
// 사용법: <input type="text" onBlur="cmm_check_english_body(this)">
// 주의사항: 아래 소스를 변형하여 검사대상문자열을 변경하여 사용
// --------------------------------------------------------------------------------------------
function checkEnglishBody(obj) {
 var str=obj.value;
 if (str.length == 0)
  return false;
 // Checks that characters are numbers or hyphens.
 for (var i = 0; i < str.length; i++) {
  var ch = str.substring(i, i + 1);
  if(ch != "-") {
   if ((ch < "A" || "z" < ch )) {
    if (ch == " ")
      ;
    else if (ch == ",")
     ;
    else
   
    return false;
   }
  }
 }
 return true;
}

// 사용빈도 : 상
// 함수명: 문자열 좌측공백제거
// 설  명: 문자열 좌측의 공백 제거 처리 함수
// 인  자: str(체크대상 문자)
// --------------------------------------------------------------------------------------------
// 사용법: str = cmm_ltrim(str);
// --------------------------------------------------------------------------------------------
function getLtrim(str) {
 while(str.substring(0,1) == ' ')
  str = str.substring(1, str.length);
 return str;
}

// 사용빈도 : 중
// 함수명: 문자열 중간공백제거
// 설  명: 문자열 중간의 공백 제거 처리 함수
// 인  자: str(체크대상 문자)
// --------------------------------------------------------------------------------------------
// 사용법: str = cmm_mtrim(str);
// --------------------------------------------------------------------------------------------
function getMtrim(str) {
 for (i=0; i < str.length;)
  if (str.substring(i,i+1) == ' ')
   str = str.substring(0,i) + str.substring(i+1,str.length);
  else
   i++;

  return str;
}

// 사용빈도 : 상
// 함수명: 문자열 우측공백제거
// 설  명: 문자열 우측의 공백 제거 처리 함수
// 인  자: str(체크대상 문자)
// --------------------------------------------------------------------------------------------
// 사용법: str = cmm_rtrim(str);
// --------------------------------------------------------------------------------------------
function getRtrim(str) {
 while(str.substring(str.length-1,str.length) == ' ')
  str = str.substring(0, str.length-1);
 return str;
}

// 사용빈도 : 상
// 함수명: 공백문자를 제외한 문자열을 리턴하는 함수
// 설  명: 공백만을 제외한 문자열을 리턴(특수문자 등도 같이 리턴)
// 인  자: arg_str(검사대상 문자열)
// --------------------------------------------------------------------------------------------
// 사용법: cmm_str_trim('abc def');
// --------------------------------------------------------------------------------------------
function getStrTrim(arg_str) {
 var rtn_str = "";
 var i=0;
 while(arg_str.charAt(i) != "") {
  if(arg_str.charAt(i)!=' ') {
   rtn_str += arg_str.charAt(i);
  }
  i++;
 }
 return rtn_str;
}

//--------------------------------------------------------------------------------------------
// Function name : getReverse
// Description   : 주어진 문자열을 거꾸로 치환
// Parameter     : str - 치환할 문자
// Return        : 치환된 문자열
//--------------------------------------------------------------------------------------------
// Usage         : getReverse("123") => "321"
//--------------------------------------------------------------------------------------------
function getReverse(Str) {
 var ret = "";

 for (var i = 0; i < Str.length; i++)
  ret = Str.substr(i, 1) + ret;
  
  return ret;
}

//--------------------------------------------------------------------------------------------
// 함수명: 특수문자를 제거하는 함수
// 설  명: 제거하고자 하는 특수문자를 제거하여 리턴하는 함수
// 인  자: str(문자열), sep(제거하고자 하는 특수문자)
// --------------------------------------------------------------------------------------------
// 사용법: <input type="text" onBlur="cmm_remove_special_char(this.value, '-%*');">
// --------------------------------------------------------------------------------------------
function getRmSpChar(str, sep) {
 var sTmp = "";
 var sBuffer = "";
 var i, j;
 var equal=false;

 for (i=0; i < str.length; i++) {
  equal = false;
  sTmp = str.substring(i, i+1);
  for(j=0; j<sep.length;j++) {
   if(sep.charAt(j) == sTmp) {
    equal = true;
    break;
   }
  }

  if(equal == false)
   sBuffer += sTmp;
 }
 //alert(sBuffer);
 return sBuffer;
}

//---------------------------------------------------------------------------------
// Function name : isEmailCheck
// Description   : 텍스트 라인안에 값을 정규식 표현을 사용해서 메일형식(ID@도메인네임)을 검사.
//                 /(\S+)@(\S+)\.(\S+)/
//                 (\S+) : white space 즉, 공백이 아닌 하나 이상의 문자열이 존재
//                  @ : 그 뒤로 골뱅이(at)가 존재하고
//                 (\S+) : 다시 문자열이 존재
//                 \. : (.)dot
//                 (\S+) : 다시 문자열이 존재
// Parameter     : 
// Return        : 
//----------------------------------------------------------------------------------
// Usage         :  isEmailCheck(this)
//----------------------------------------------------------------------------------
function isEmailCheck(email) {
    mvalue = email ;
   
    if (mvalue.value == null || mvalue.value == "") return;
   
    if (mvalue.value.search(/(\S+)@(\S+)\.(\S+)/) == -1) {
   alert ("ID@고유도메인명 형식으로 입력하세요!!\n\n예) test@hanmail.net");
   
   mvalue.value = "";
   mvalue.focus();
   return false;
    } else {
   // alert("입력하신 메일 주소는\n\n" + mvalue.value + "\n\n입니다.");
   return false;
    }
}

//------------------------------------------------------------------
// Function name : fnBluring
// Description   :
// Parameter     :  
// Return        : 
//------------------------------------------------------------------
// Usage         :  
//------------------------------------------------------------------

function fnBluring() {
 if(event.srcElement.tagName=="A"||event.srcElement.tagName=="IMG"||event.srcElement.tagName=="Onclick"||event.srcElement.tagName=="TABLE")
    document.body.focus();
}

//------------------------------------------------------------------
// Function name : fnBsControl
// Description   : 백스페이스 제어
// Parameter     :  
// Return        : 
//------------------------------------------------------------------
// Usage         :  
//------------------------------------------------------------------
function fnBsControl() {
 var d = document;
 //var sw = 0;
   
  if (window.event.keyCode==8) {
  // 등록된 객체이름을 백스페이스 방지
  //if (d.objList == null)
  //{
  //    return false;
  //}
  //else
  //{
  //    for (i=0; i<d.objList.length; i++)
  //    {
  //         if (window.event.srcElement.name == d.objList[i].name)
  //         {
  //            sw = 1;         
  //            break;      
  //         }
  //    }
  //   
  //    if (sw == 0)
  //    {
  //        return false;
  //    }
  //}
 
  // 폼객체의 종류로 백스페이스 방지
  if (window.event.srcElement.type != 'text') {
   return false;   
  }
  }
}

//------------------------------------------------------------------
// Function name : isValidDay
// Description   : 지정 년,월,일이 달력상으로 존재하는 날짜인지 검사
// Parameter     : year - 년 , month - 월 , day - 일 
// Return        : 
//------------------------------------------------------------------
// Usage         :  
//------------------------------------------------------------------
 
function isValidDay(year, month, day) {   
 var m = parseInt(month,10) - 1;
 var d = parseInt(day,10);

 var end = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
  end[1] = 29;
 }

 return (d >= 1 && d <= end[m]);

Posted by 1010
반응형

The Calendar widget is a JavaScript-based calendar that can either be embedded within a page or popup when a trigger element is clicked. It is based very loosely on the Dynarch Calendar, only in the sense that it was used as a base, but has been almost entirely re-implemented.

Like CalendarView? Try my JavaScript list selection tool, MatrixView!

Features

  • Developed with CSS in Mind
    In CalendarView you will find no embedded style or presentation. You are encouraged to make it look how you want it to look so that it looks like it belongs in your project.
  • Embedded or Popup — You Decide!
    CalendarView can be either embedded into your page or used as a pop-up. The choice is yours!
  • Lightweight and Easy to Use
    Frustrated with the complexity and bloatedness of existing calendars, CalendarView was implemented as a lightweight alternative.
  • Utilizes the Prototype Framework
    CalendarView uses the Prototype JavaScript framework, lessening the overall JavaScript impact if Prototype is already being used in your project.

Examples

Embedded Calendar

April 2009
« Today »
S M T W T F S
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 1 2

2009-04-08

Popup Calendar

2009-03-08

Download

CalendarView requires Prototype 1.6.0 (or later).

You may also access the source code at GitHub.

Release History

Version 1.1 — October 19th, 2008

  • Upgraded to Prototype 1.6 and cleaned up code to take full advantage of its new API features.
  • Removed our dependency on Builder from script.aculo.us, as Prototype 1.6 has its own DOM Builder now
  • Fixed a bug where navigating through months of the calendar would display the wrong year when you reached December. Thanks to Dirk Koritnik for the fix and to everyone who reported the issue.

Version 1.0 — March 12th, 2007

  • Initial release

Development Roadmap

  • Add support for assigning an HTML ID and CSS classes to the Calendar at time of creation
  • Reuse Calendar objects for Popup Calendars instead of creating new objects
  • Cleanup, extract, or remove the Date object extensions

Support CalendarView Development

CalendarView is developed in the author's spare time. If you find it to be useful within your web application, please consider making a small donation to support and encourage future development.

Usage Instructions

Options

Option Description
dateField An HTML element (or DOM ID) that will be updated when a date is selected. Can be an INPUT field or any other JavaScript object that has either innerHTML or value attributes. The value of this field will also be parsed for setting the current date when the Calendar is initialized.
triggerElement An HTML element (or DOM ID) that will be observed for clicks to display a popup calendar. If a triggerElement is not specified, the dateField will be observed instead.
parentElement An HTML element (or DOM ID) that will receive the initialized embedded calendar.
selectHandler JavaScript function that will be called when a date is selected. Only define this if you want to override the default behavior.
closeHandler JavaScript function that will be called when the calendar should be closed (either after a selection has been made or if the user clicked outside of the calendar's container element). This only applies to popup calendars and should only be defined if you want to override the default behavior.

Setting up an Embedded Calendar

Embedded calendars require a parent element so that it can be appended to the DOM, such as a div element.

Embedded Calendar Example

<html>
  <head>
    ...
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript" src="calendarview.js"></script>
    <script type="text/javascript">
      window.onload = function() {
        Calendar.setup({
          dateField     : 'date',
          parentElement : 'calendar'
        })
      }
    </script>
    ...
  </head>
  <body>
    ...
    <div id="calendar"></div>
    <div id="date">Select Date</div>
    ...
  </body>
</html>

Setting up a Popup Calendar

Popup calendars require a trigger element that will display the calendar when clicked. By default, the element defined as the dateField will trigger the calendar if a triggerElement has not been specified.

Popup Calendar Example

<html>
  <head>
    ...
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript" src="calendarview.js"></script>
    <script type="text/javascript">
      window.onload = function() {
        Calendar.setup({
          dateField      : 'date',
          triggerElement : 'calendarButton'
        })
      }
    </script>
    ...
  </head>
  <body>
    ...
    <input type="text" name="date" id="date" />
    <input type="button" id="calendarButton" value="Show Calendar" />
    ...
  </body>
</html>

Styling the Calendar

The calendar is meant to be styled entirely with CSS. A few CSS classes are declared in the HTML output to assist in styling, but for the most part it should be styled with standard CSS element selectors.

Example HTML Output

<div class="calendar popup">
  <table>
    <thead>
      <tr>
        <td class="title" colspan="7">March 2007</td>
      </tr>
      <tr>
        <td class="button">«</td>
        <td class="button">‹</td>
        <td class="button" colspan="3">Today</td>
        <td class="button">›</td>
        <td class="button">»</td>
      </tr>
      <tr>
        <th class="weekend">S</th>
        <th>M</th>
        <th>T</th>
        <th>W</th>
        <th>T</th>
        <th>F</th>
        <th class="weekend">S</th>
      </tr>
    </thead>
    <tbody>
      <tr class="days">
        <td class="otherDay weekend">25</td>
        <td class="otherDay">26</td>
        <td class="otherDay">27</td>
        <td class="otherDay">28</td>
        <td>1</td>
        <td>2</td>
        <td class=" weekend">3</td>
      </tr>
      <tr class="days">
        <td class="weekend">4</td>
        <td>5</td>
        <td class="selected">6</td>
        <td>7</td>
        <td>8</td>
        <td>9</td>
        <td class="weekend">10</td>
      </tr>
      <tr class="days">
        <td class="weekend">11</td>
        <td class="today">12</td>
        <td>13</td>
        <td>14</td>
        <td>15</td>
        <td>16</td>
        <td class="weekend">17</td>
      </tr>
      <tr class="days">
        <td class="weekend">18</td>
        <td>19</td>
        <td>20</td>
        <td>21</td>
        <td>22</td>
        <td>23</td>
        <td class="weekend">24</td>
      </tr>
      <tr class="days">
        <td class="weekend">25</td>
        <td>26</td>
        <td>27</td>
        <td>28</td>
        <td>29</td>
        <td>30</td>
        <td class="weekend">31</td>
      </tr>
    </tbody>
  </table>
</div>
Posted by 1010
반응형
Posted by 1010
반응형
<script language="javascript">
function printWindow() {
factory.printing.header = ""
factory.printing.footer = ""
factory.printing.portrait = true
factory.printing.leftMargin = 0.45
factory.printing.topMargin = 0.45
factory.printing.rightMargin = 0.45
factory.printing.bottomMargin = 0.0
factory.printing.Print(true, window);
}
</script>
</head>

<body link=blue vlink=purple onload="printWindow();" topmargine="18">
<object id=factory style="display:none" classid="clsid:1663ed61-23eb-11d2-b92f-008048fdd814" codebase="/smrcptroot/print/smsx.cab#Version=6,4,438,06">
</object>
.
.
.
<%
// dataPerPage : 한 페이지에 보여줄 data 갯수
// currentPage : 현재 페이지
// totalPage : 전체 페이지
int dataPerPage = 2;
int currentPage = 0;
int totalPage = data.size() / dataPerPage;
if ((data.size() % dataPerPage) > 0) totalPage += 1;

for (int i = 0; i < totalPage; i++) {
currentPage = i + 1;

%>
Posted by 1010
반응형
<html>
<head>
    <title>http://technote.co.kr</title>
<style>
    #bannerbox .oherpromotion {display:inline; position:relative; float:left; margin:3px 11px 0 0 ; }
    #bannerbox .oherpromotion h3 {float:left; width:188px; height:20px; background:url(http://imgshopping2.naver.com/2007/new/main/bg_oftenview.gif) no-repeat left top; color:#666; font-weight:normal; font-size:12px; text-align:left; letter-spacing:-1px}
    #bannerbox .oherpromotion h3 a {display:block; width:184px; height:16px; padding:4px 0 0 7px; color:#666; text-decoration:none;}
    #bannerbox .oherpromotionlist {position:absolute; left:0px; top:18px; width:188px; background:url(http://imgshopping2.naver.com/2007/new/main/bg_ranking_list_mid.gif) repeat-y left top; z-index:100;}
    #bannerbox .oherpromotioninner {background:url(http://imgshopping2.naver.com/2007/new/main/bg_ranking_list_bottom.gif) no-repeat left bottom;}
    #bannerbox .oherpromotionlist ul {width:158px; margin:0 8px; padding:3px 0; overflow:hidden;}
    #bannerbox .oherpromotionlist li {width:100%; padding:6px 0 4px 0; background:url(http://imgshopping2.naver.com/2007/new/rankingshop/dot_gray01.gif) repeat-x left top; font-size:12px; vertical-align:top; line-height:1em; letter-spacing:-1px; text-align:left;}
    #bannerbox .oherpromotionlist li a {padding-left:15px; background:url(http://imgshopping2.naver.com/2007/new/rankingshop/bu_arrow02.gif) no-repeat 3px top; color:#7f7f7f;}
    #bannerbox .oherpromotionlist li a:hover {color:#64a32f;}

</style>
<script>
function toggleView(target){
    var sTarget = target.href.split("#");
    var aTarget = document.getElementById(sTarget[sTarget.length-1]);
    if(aTarget.style.display == "none") aTarget.style.display = "block";
    else aTarget.style.display = "none";   
}
</script>
</head>
<body>
<div id="bannerbox">
    <div class="oherpromotion">
    <h3><a href="#oherpromotionview" onClick="toggleView(this); return false;" onfocus=this.blur()>네이버 콤보스타일 메뉴</a></h3>
        <div id="oherpromotionview" class="oherpromotionlist" style="display:none;">
            <div class="oherpromotioninner">
                <ul>
                    <li><A HREF="http://technote.co.kr">테크 1</A>
                    <li><A HREF="http://technote.co.kr">테크 2</A>
                    <li><A HREF="http://technote.co.kr">테크 3</A>
                    <li><A HREF="http://technote.co.kr">테크 4</A>
                    <li><A HREF="http://technote.co.kr">테크 5</A>
                    <li><A HREF="http://technote.co.kr">테크 6</A>
                    <li><A HREF="http://technote.co.kr">테크 7</A>
                    <li><A HREF="http://technote.co.kr">테크 8</A>
                    <li><A HREF="http://technote.co.kr">테크 9</A>
                    <li><A HREF="http://technote.co.kr">테크 10</A>
                </ul>
            </div>
        </div>
    </div>
</div>
</body>
 
Posted by 1010
반응형

<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=euc-kr">

<style>
.ellipsis  {font:9pt "굴림"; width:100%; overflow:hidden; text-overflow:ellipsis; text-align:left; }
.colresize {font:9pt "굴림"; cursor:""; }
.input_box {width:expression(this.parentNode.clientWidth-8); }
</style>

<SCRIPT LANGUAGE="JavaScript">
<!--
// 자료출처 : phpschool.com ==> kisses
var mousedown = false; //마우스를 누른 상태
var td = "";           //사이즈 변경할 td
var td_width;          //변경할 td의 width,
var x = 0;             //마우스 드레그전 가로위치

function TCstartColResize(obj){
       mousedown = true;
       td = obj;
       td_width = td.width;
       x = event.clientX;
}
function TCColResize()
{
       if (mousedown){
              var distX = event.x - x; //이동한 간격
              td.width = parseInt(td_width) + parseInt(distX);
       }
}
function TCstopColResize(){
       mousedown = false;
       td = '';
}

function cell_left(obj){//마우스가 셀의 왼쪽인지 측정
       if(event.offsetX < 5 && obj.cellIndex!=0)
              return true;
       else
              return false;
}
function cell_right(obj){//마우스가 셀의 오른쪽인지 측정
       if(event.offsetX > obj.width-4)
              return true;
       else
              return false;
}

//리사이즈시작
document.onmousedown = function(){
try{
       var now_mousedown = window.event.srcElement;
       if(now_mousedown.className.toUpperCase()=="COLRESIZE"){
              if( cell_left(now_mousedown) ){
                     now_mousedown = now_mousedown.parentNode.childNodes[now_mousedown.cellIndex-1];
              }else if( !cell_right(now_mousedown) ){
                     return true;//오른쪽도 왼쪽도 아니면 사이즈 조절 안함
              }
              TCstartColResize(now_mousedown);
       }
}catch(e){ return true; }
}

//리사이즈
document.onmousemove = function(){
try{
       var now_mousemove = window.event.srcElement;
       if(now_mousemove.className.toUpperCase()=="COLRESIZE" || td!=""){

              //셀의 가장자리면 마우스 커서 변경
              if( cell_left(now_mousemove) || cell_right(now_mousemove) ){
                     now_mousemove.style.cursor = "col-resize";
              }else{
                     now_mousemove.style.cursor = "";
              }

              TCColResize(now_mousemove);
       }else{
              now_mousemove.style.cursor = "";
    }
}catch(e){ return true; }
}

//리사이즈종료
document.onmouseup = function(){
try{
       var now_mouseup = window.event.srcElement;
       //if(now_mouseup.className=="colResize"){
              TCstopColResize(now_mouseup);
       //}
}catch(e){ return true; }
}

//리사이즈 도중 텍스트 선택 금지
document.onselectstart = function(){
try{
    if(td != ""){
        return false;
    }
}catch(e){ return true; }
}
//-->
</SCRIPT>
</HEAD>

<BODY>
<div style="width:100%;height:100;overflow-x:auto;overflow-y:auto">
    <table width="430" border="0" cellpadding="3" cellspacing="1" bgcolor="#B8B8B8" nowrap style='table-layout:fixed'>
        <tr bgcolor="#A5D4D2" align="center" height="25">
            <td width="35"  class="colresize">선택</td>
            <td width="35"  class="colresize">순번</td>
            <td width="70" class="colresize">품목명</td>
            <td width="30"  class="colresize">수량</td>
            <td width="50"  class="colresize">단위</td>
            <td width="70"  class="colresize">날짜</td>
            <td width="70"  class="colresize">장소</td>
            <td width="70" class="colresize">비고</td>
        </tr>
        <tr bgcolor="#FFFFFF" height="27" align="center">
            <td><Input type="radio" name="radio"></td>
            <td>1</td>
            <td><input type='text' class="input_box"></td>
            <td><input type='text' class="input_box"></td>
            <td><select class="input_box"><option>EA</option></select></td>
            <td><input type='text' class="input_box"></td>
            <td><input type='text' class="input_box"></td>
            <td nowrap class="ellipsis">비고 비고 비고 비고 비고 비고 비고 비고 비고</td>
        </tr>
    </table>
</div>
</BODY>
</HTML>

Posted by 1010
반응형

<style type="text/css">

#minitabs{
margin:0;
padding: 0 0 20px 10px;
border-bottom: 1px solid #696;
}

#minitabs li{
margin: 0;
padding: 0;
display: inline;
list-style-type:none;
}



#minitabs a{
 float: left;
 line-height: 14px;
 font-weight: bold;
 margin: 0 10px 4px 10px;
 text-decoration:none;
 font-size: 12px;
 color: #9c9; // 처음 보이는 기본 색깔
}


#minitabs a.active, #minitabs a:hover {
 border-bottom: 4px solid #232; // 글씨 위에 마우스 올릴때  라인 색깔
 padding-bottom: 2px; //글씨에 라인이 떨어질 위치(거리)

 color: #344;  // active 되었을때 색깔
}


 

#minitabs a:hover{
color: #696; // 글씨 위에 마우스 올릴때 색깔
}


</style>


<body>

<ul id="minitabs">
<li><a href="#" class="active">링크</a></li>   // 하이라이트된 탭이 계속 켜져있게 하기
<li><a href="#">책</a></li>
<li><a href="#">영화</a></li>
<li><a href="#">음악</a> </li>
</ul>
</body>

Posted by 1010
반응형

사용자 삽입 이미지



<script language="javascript">

var fixedX = -1; ////////// 레이어 X축 위치 (-1 : 버튼에 바로 아래에 표시)
var fixedY = -1; ////////////// 레이어 Y축 위치 (-1 : 버튼에 바로 아래에 표시)
var startAt = 0; ///////////// 일요일 표시 부분 / 0 : 일요일(일월화...) / 1 : 월요일(...금토일)
var showToday = 1; // 오늘 날자 표시 유무 - 0 : 감춤 / 1 : 보임
var imgDir = './'; // 이미지 디렉토리 - ./ : 현재 디렉토리

/////////////////////////////// 각 변수 선언 ///////////////////
var crossobj, crossMonthObj, crossYearObj, monthSelected, yearSelected, dateSelected, omonthSelected, oyearSelected, odateSelected, monthConstructed, yearConstructed, intervalID1, intervalID2, timeoutID1, timeoutID2, ctlToPlaceValue, ctlNow, dateFormat, nStartingMonth, nStartingYear

var bPageLoaded = false;
var ie = document.all;
var dom = document.getElementById;
var bShow = false;
var ns4 = document.layers;

var today = new    Date(); /////////////// 날자 변수 선언
var dateNow = today.getDate(); //////////////// 로컬 컴퓨터의 일(day)을 구함 
var monthNow = today.getMonth(); ///////////////// 로컬 컴퓨터의 월(month)을 구함
var yearNow = today.getYear(); ///////////////// 로컬 컴퓨터의 년(year)을 구함

var    monthName =    new    Array("1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월")
var    monthName2 =    new    Array("1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월")

if (startAt==0) {
    dayName = new Array    ("일","월","화","수","목","금","토")
} else {
    dayName = new Array    ("월","화","수","목","금","토","일")
}
var oPopup = window.createPopup();
var oPopBody = oPopup.document.body;
var strCalendar;
var cleft;
var ctop;

if(dom) {
    strCalendar = "<img src='' width=0 height=0>";
    strCalendar += "<style type='text/css'>";
    strCalendar += "td {font-size:12px; font-family:굴림; text-decoration:none; }";
    strCalendar += "A:link,A:active,A:visited{text-decoration:none;font-size:12PX;color:#333333;}";
    strCalendar += "A:hover {text-decoration:none; color:ff9900}";
    strCalendar += "font { font-size: 9pt; }";
    strCalendar += ".cnj_close {font-size:8pt;color:#000000; background-color:#EFEFEF; border-width:1; border-color:#808080; border-style:solid;cursor:hand;font-weight:bold;height:16px;width:16px;text-align:center;vertical-align:bottom}";
    strCalendar += ".cnj_close2 {font-size:8pt;color:#000000; background-color:#EFEFEF; border-width:1; border-color:#808080; border-style:solid;cursor:hand;font-weight:bold;height:16px;width:16px;text-align:center;vertical-align:bottom}";
    strCalendar += ".cnj_input {background-color:rgb(240,240,240);border-width:1pt; height:16pt;cursor:hand;}";
    strCalendar += ".cnj_input2 {font-size:8pt;color:#808080; background-color:#EFEFEF; border-width:1; border-color:#808080; border-style:solid;cursor:hand;height:16px;}";
    strCalendar += ".cnj_input3 {font-size:8pt;color:#000000; background-color:#FFFFFF; border-width:1; border-color:#C00000; border-style:solid;cursor:hand;height:16px;}";
    strCalendar += ".cnj_input4 {font-size:8pt;color:#C00000; background-color:#FFFFFF; border-width:1; border-color:#808080; border-style:solid;cursor:hand;height:16px;}";
    strCalendar += ".cnj_td {border-width:1;border-style:solid;border-color:#a0a0a0;}";
    strCalendar += "</style>";

    strCalendar += "<div id='calendar' style='z-index:+999;position:absolute;;'>";
    strCalendar += "<table width='190' class='cnj_td'>";
    strCalendar += "    <tr bgcolor='#EEEEEE' height=20>";
    strCalendar += "        <td>";
    strCalendar += "            <table width='188' border=0>";
    strCalendar += "                <tr height=20>";
    strCalendar += "                    <td style='padding:0px;'><font color='#ffffff'><B><span id='caption'></span></B></font></td>";
    strCalendar += "                    <td align=right><input type='button' value='x' class='cnj_close' title='닫기' onclick='parent.oPopup.hide()' onfocus='this.blur()' onMouseover=\"this.className='cnj_close2'\" onMouseout=\"this.className='cnj_close'\"></td>";
    strCalendar += "                </tr>";
    strCalendar += "            </table>";
    strCalendar += "        </td>";
    strCalendar += "    </tr>";
    strCalendar += "    <tr height=1>";
    strCalendar += "        <td style='padding:3px' bgcolor=#ffffff><span id='content'></span></td>";
    strCalendar += "    </tr>";
           
    if(showToday==1) {
        strCalendar += "<tr bgcolor=#f0f0f0 height=20><td style='padding:5px' align=center><span id='lblToday'></span></td></tr>";
    }
           
    strCalendar += "</table>";
    strCalendar += "</div>";
    strCalendar += "<div id='selectMonth' style='z-index:+999;position:absolute;display:none;'></div> ";
    strCalendar += "<div id='selectYear' style='z-index:+999;position:absolute;display:none;'></div>";
    oPopBody.innerHTML = strCalendar;
}

function init() {
    if(!ns4) {
        if(!ie) {
            yearNow += 1900;
        }

        crossobj = oPopBody.all.calendar;
        crossMonthObj = oPopBody.all.selectMonth;
        crossYearObj = oPopBody.all.selectYear;
        monthConstructed = false;
        yearConstructed = false;

        sHTML1="<input type='button' value='◀' class='cnj_input2' onClick='javascript:parent.movedecMonth()' onfocus='this.blur()' title='이전 달(월)로 이동' "
        sHTML1+="onMouseover=\"this.className='cnj_input3';window.status='이전 달(월)로 이동'\" onMouseout=\"this.className='cnj_input2';window.status=''\"> </span> "

        sHTML1+="<input type='button' value='▶'  class='cnj_input2' onClick='javascript:parent.moveincMonth()' onfocus='this.blur()' title='다음 달(월)로 이동' "
        sHTML1+="onMouseover=\"this.className='cnj_input3';window.status='다음 달(월)로 이동'\"  onMouseout=\"this.className='cnj_input2';window.status=''\"> </span> "

        sHTML1+="<span id='spanMonth'  class='cnj_input4' onclick='parent.popUpMonth()' title='월 선택' "
        sHTML1+="onMouseover=\"this.className='cnj_input3';window.status='월 선택'\" onMouseout=\"this.className='cnj_input4';window.status=''\"></span>&nbsp;";

        sHTML1+="<span id='spanYear'  class='cnj_input4' onclick='parent.popUpYear()' title='년도 선택' "
        sHTML1+="onMouseover=\"this.className='cnj_input3';window.status='년도 선택'\" onMouseout=\"this.className='cnj_input4';window.status=''\"></span> ";

        oPopup.document.getElementById("caption").innerHTML = sHTML1;
        bPageLoaded = true;
       
        if(showToday==1) {
            oPopup.document.getElementById("lblToday").innerHTML =    ""+
            "<div onmousemove='window.status=\"오늘 날짜로 표시하기\"' onmouseout='window.status=\"\"' title='오늘 날짜로 표시하기' "+
            //" style='"+styleAnchor+"' href='javascript:monthSelected=monthNow;yearSelected=yearNow;constructCalendar();' onFocus='this.blur()'>"+
            " style='"+styleAnchor+"' onclick=parent.totoday() onFocus='this.blur()'>"+
            "오늘 날짜 :  "+yearNow+"년 "+
            ""+monthName[monthNow].substring(0,3)+" "+
            ""+dateNow+"일 "+  // 일
            "</div>";
        }       
    }
}

function totoday(){ // 오늘 날짜로 표시하기
    monthSelected=monthNow;
    yearSelected=yearNow;
    constructCalendar();
}

function HolidayRec(d, m, y, desc) {
    this.d = d;
    this.m = m;
    this.y = y;
    this.desc = desc;
}

var HolidaysCounter = 0;
var Holidays = new Array();

function addHoliday(d, m, y, desc) {
    Holidays[HolidaysCounter++] = new HolidayRec ( d, m, y, desc );
}

var styleAnchor = "text-decoration:none;color:black;cursor:hand;width:100%;height:100%";
var styleLightBorder = "border-style:solid;border-width:1px;border-color:#a0a0a0;text-decoration:underline;font-weight:bold;cursor:hand;width:100%;height:100%";

function padZero(num) {
    return (num < 10)? '0' + num : num;
}

function constructDate(d,m,y) {
    sTmp = dateFormat
    sTmp = sTmp.replace("dd","<e>");
    sTmp = sTmp.replace("d","<d>");
    sTmp = sTmp.replace("<e>",padZero(d));
    sTmp = sTmp.replace("<d>",d);
    sTmp = sTmp.replace("mmmm","<p>");
    sTmp = sTmp.replace("mmm","<o>");
    sTmp = sTmp.replace("mm","<n>");
    sTmp = sTmp.replace("m","<m>");
    sTmp = sTmp.replace("<m>",m+1);
    sTmp = sTmp.replace("<n>",padZero(m+1));
    sTmp = sTmp.replace("<o>",monthName[m]);
    sTmp = sTmp.replace("<p>",monthName2[m]);
    sTmp = sTmp.replace("yyyy",y);

    return sTmp.replace("yy",padZero(y%100));
}

function closeCalendar() {
    oPopup.hide();
    ctlToPlaceValue.value =    constructDate(dateSelected,monthSelected,yearSelected);
}

function moveincMonth() {
    monthSelected++;

    if (monthSelected>11) {
        monthSelected=0;
        yearSelected++;
    }
    constructCalendar();
}

function movedecMonth() {
    monthSelected--;

    if (monthSelected<0) {
        monthSelected=11;
        yearSelected--;
    }
    constructCalendar();
}

function incMonth() {
    if (nStartingMonth + 6 == 12) return;
    for(i = 0; i < 7; i++) {
        newMonth = (i + nStartingMonth) + 1;

        if (newMonth > 12) {nStartingMonth--; break;}
        if (newMonth == monthSelected + 1) {
            txtMonth = " <B>"+ newMonth +"월</B> ";
        } else {
            txtMonth = " " + newMonth + "월";
        }
        oPopup.document.getElementById("m"+i).innerHTML = txtMonth;
    }
    nStartingMonth++;
    bShow = true;
}

function decMonth() {
    if (nStartingMonth == 1) return;
    for (i=0; i<7; i++) {
        newMonth    = (i+nStartingMonth)-1;

        if (newMonth < 1) {nStartingMonth++; break;}
        if (newMonth==monthSelected + 1) {
            txtMonth = " <B>"+ newMonth +"월</B> ";
        } else {
            txtMonth = " " + newMonth + "월";
        }
        oPopup.document.getElementById("m"+i).innerHTML = txtMonth;
    }
    nStartingMonth--;
    bShow = true;
}

function selectMonth(nMonth) {
    monthSelected = parseInt(nMonth + nStartingMonth - 1);
    monthConstructed = false;
    constructCalendar();
    popDownMonth();
}

function constructMonth() {
    popDownYear();
    sHTML =    "";

    if(!monthConstructed) { // 월 이전 월 링크
        sHTML ="<tr><td align='center' style='cursor:pointer'     "
        sHTML +="    onmouseover='this.style.backgroundColor=\"#FFCC99\"' "
        sHTML +="    onmouseout='clearInterval(parent.intervalID1);this.style.backgroundColor=\"\"'  "
        sHTML +="    onmousedown='clearInterval(parent.intervalID1);parent.intervalID1=setInterval(\"parent.decMonth()\",30)' "
        sHTML +="    onmouseup='clearInterval(parent.intervalID1)'> "
        sHTML +="    ▲</td></tr>";
        j = 0;
       
        var nSelectedMonth = monthSelected + 1;
       
        nStartingMonth = (nSelectedMonth - 3) < 1 ? 1 : nSelectedMonth - 3; //시작월 - 3 이 1보다 작으면 1로 고정
        nStartingMonth = nStartingMonth > 6 ? 6 : nStartingMonth; //시작월이 6보다 크면 6로 고정 (6 시작 월 + 목록 숫자 6 = 12 종료 월)

        var nEndMonth = (nSelectedMonth + 3) > 12 ? 12 : (nSelectedMonth + 3); // 종료월 + 3이 12보다 크면 12로 고정
        nEndMonth = nEndMonth < 7 ? 7 : nEndMonth; //종료 월이 7보다 작으면 7로 고정
       
        for (i = nStartingMonth; i <= nEndMonth; i++) {
            sName =    i;

            //////////////// 현재 월 ////////////////////////
            if (i == nSelectedMonth) { sName = "<b>" + sName + "</b>" }
            sHTML +="<tr><td height='15' id='m" + j + "' onmouseover='this.style.backgroundColor=\"#FFCC99\"' onmouseout='this.style.backgroundColor=\"\"' "
            sHTML +=" style='cursor:pointer' onClick='parent.selectMonth("+j+");event.cancelBubble=true'> " + sName + "월"
            sHTML +="</td></tr>";
            j ++;
        }
       
         // 월 다음 월 링크
        sHTML += "<tr><td align='center' onmouseover='this.style.backgroundColor=\"#FFCC99\"' style='cursor:pointer' "
        sHTML += " onmouseout='clearInterval(parent.intervalID2);this.style.backgroundColor=\"\"' "
        sHTML += " onmousedown='clearInterval(parent.intervalID2);parent.intervalID2=setInterval(\"parent.incMonth()\",30)'    "
        sHTML += " onmouseup='clearInterval(parent.intervalID2)'> "
        sHTML += " ▼</td></tr>";

          /////// 월 표 크기 ///////////////////////////////
        oPopup.document.getElementById("selectMonth").innerHTML    = ""+
        "<table width='50' style='font-family:굴림; font-size:11px; border-width:1; border-style:solid; border-color:#a0a0a0;' bgcolor='#FFFFDD' "+
        " onmouseover='clearTimeout(parent.timeoutID2)' "+
        " onmouseout='clearTimeout(parent.timeoutID2);parent.timeoutID2=setTimeout(\"parent.popDownMonth()\",100)' cellspacing=0>"+
        ""+ sHTML    + ""+
        "</table>";
        monthConstructed    = true;
    }
}

function popUpMonth() {
    constructMonth();
    crossMonthObj.style.display = "";
    crossMonthObj.style.left = crossobj.style.left + 50;
    crossMonthObj.style.top = crossobj.style.top + 26;
}

function popDownMonth()    {
    crossMonthObj.style.display = "none";
}

function incYear() {
    for(i=0; i<7; i++) {
        newYear    = (i+nStartingYear)+1;

        if (newYear==yearSelected) {
            txtYear = " <B>"+ newYear +"년  </B> ";
        } else {
            txtYear = " " + newYear + "년  ";
        }
        oPopup.document.getElementById("y"+i).innerHTML = txtYear;
    }
    nStartingYear++;
    bShow = true;
}

function decYear() {
    for (i=0; i<7; i++) {
        newYear    = (i+nStartingYear)-1;

        if (newYear==yearSelected) {
            txtYear = " <B>"+ newYear +"년  </B> ";
        } else {
            txtYear = " " + newYear + "년  ";
        }
        oPopup.document.getElementById("y"+i).innerHTML = txtYear;
    }
    nStartingYear--;
    bShow = true;
}

function selectYear(nYear) {
    yearSelected = parseInt(nYear+nStartingYear);
    yearConstructed = false;
    constructCalendar();
    popDownYear();
}

function constructYear() {
    popDownMonth();
    sHTML =    "";

    if(!yearConstructed) { // 년도 이전 년도 링크
        sHTML ="<tr><td align='center' style='cursor:pointer'     "
        sHTML +="    onmouseover='this.style.backgroundColor=\"#FFCC99\"' "
        sHTML +="    onmouseout='clearInterval(parent.intervalID1);this.style.backgroundColor=\"\"'  "
        sHTML +="    onmousedown='clearInterval(parent.intervalID1);parent.intervalID1=setInterval(\"parent.decYear()\",30)' "
        sHTML +="    onmouseup='clearInterval(parent.intervalID1)'> "
        sHTML +="    ▲</td></tr>";
        j = 0;
        nStartingYear =    yearSelected-3;

        for (i=(yearSelected-3); i<=(yearSelected+3); i++) {
            sName =    i;

            if (i==yearSelected) { sName =    "<b>" +    sName +    "</b>" }
            sHTML +="<tr><td height='15' id='y" + j + "' onmouseover='this.style.backgroundColor=\"#FFCC99\"' onmouseout='this.style.backgroundColor=\"\"' "
            sHTML +=" style='cursor:pointer' onClick='parent.selectYear("+j+");event.cancelBubble=true'> " + sName + "년  "
            sHTML +="</td></tr>";
            j ++;
        }
       
         // 년도 다음 년도 링크
        sHTML += "<tr><td align='center' onmouseover='this.style.backgroundColor=\"#FFCC99\"' style='cursor:pointer' "
        sHTML += " onmouseout='clearInterval(parent.intervalID2);this.style.backgroundColor=\"\"' "
        sHTML += " onmousedown='clearInterval(parent.intervalID2);parent.intervalID2=setInterval(\"parent.incYear()\",30)'    "
        sHTML += " onmouseup='clearInterval(parent.intervalID2)'> "
        sHTML += " ▼</td></tr>";

         /////// 년도 표 크기 ///////////////////////////////
        oPopup.document.getElementById("selectYear").innerHTML    = ""+
        "<table width='55' style='font-family:굴림; font-size:11px; border-width:1; border-style:solid; border-color:#a0a0a0;' bgcolor='#FFFFDD' "+
        " onmouseover='clearTimeout(parent.timeoutID2)' "+
        " onmouseout='clearTimeout(parent.timeoutID2);parent.timeoutID2=setTimeout(\"parent.popDownYear()\",100)' cellspacing=0>"+
        ""+ sHTML    + ""+
        "</table>";
        yearConstructed    = true;
    }
}

function popDownYear() {
    clearInterval(intervalID1);
    clearTimeout(timeoutID1);
    clearInterval(intervalID2);
    clearTimeout(timeoutID2);
    crossYearObj.style.display = "none";
}

function popUpYear() {
    constructYear();
    crossYearObj.style.display = "";
    crossYearObj.style.left = crossobj.style.left + (6 + oPopup.document.getElementById("spanYear").offsetLeft) + "px";
    crossYearObj.style.top = crossobj.style.top + 26;
}

function constructCalendar() {
    var aNumDays = Array (31,0,31,30,31,30,31,31,30,31,30,31);
    var dateMessage;
    var startDate =    new Date (yearSelected,monthSelected,1);
    var endDate;
    var intWeekCount = 1;
   
    if(monthSelected==1) {
        endDate    = new Date (yearSelected,monthSelected+1,1);
        endDate    = new Date (endDate    - (24*60*60*1000));
        numDaysInMonth = endDate.getDate();
    } else {
        numDaysInMonth = aNumDays[monthSelected];
    }

    datePointer = 0;
    dayPointer = startDate.getDay() - startAt;
       
    if(dayPointer<0) {
        dayPointer = 6;
    }
    sHTML =    "<table     border=0 style='font-family:verdana;font-size:10px;'><tr height=16>";

    for(i=0; i<7; i++) {   /////// 요일 ///////////////////////
        sHTML += "<td width='27' align='right'><B>"+ dayName[i]+"</B></td>";
    }
    sHTML +="</tr><tr height=16>";
       
    for(var i=1; i<=dayPointer;i++)    {  // 빈 날짜
        sHTML += "<td> </td>";
    }
   
    for(datePointer=1; datePointer<=numDaysInMonth; datePointer++) {
        dayPointer++;
        sHTML += "<td align=right>";
        sStyle = styleAnchor;

        if((datePointer==odateSelected) && (monthSelected==omonthSelected) && (yearSelected==oyearSelected)) {
            sStyle += styleLightBorder;
        }
        sHint = "";

        for(k=0;k<HolidaysCounter;k++) {
            if((parseInt(Holidays[k].d)==datePointer)&&(parseInt(Holidays[k].m)==(monthSelected+1))) {
                if((parseInt(Holidays[k].y)==0)||((parseInt(Holidays[k].y)==yearSelected)&&(parseInt(Holidays[k].y)!=0))) {
                    sStyle+="background-color:#FFDDDD;";
                    sHint+=sHint==""?Holidays[k].desc:"\n"+Holidays[k].desc;
                }
            }
        }
        var regexp= /\"/g;
        sHint=sHint.replace(regexp,"&quot;");
        /////////////// 날짜 선택시 ==> 마우스가 날짜 위로 갔을때 ///////////////////////////////
        dateMessage = "title=' 날짜 선택 : "+ yearSelected + "년 " +    monthName[monthSelected] +" "  + datePointer + "일"+"' onmousemove='window.status=\" 날짜 선택 : "+ yearSelected + "년 " +    monthName[monthSelected] +" "  + datePointer + "일"+"\"' onmouseout='window.status=\"\"' ";

        if((datePointer == dateNow) && (monthSelected == monthNow) && (yearSelected == yearNow)) {  // 현재 오늘 날짜
            sHTML += "<b><div style='"+sStyle+"' onclick='javascript:parent.dateSelected="+datePointer+";parent.closeCalendar();'><font color=#0000C0> " + datePointer + "</font> </div></b>";
        } else
        if((dayPointer % 7 == (startAt * -1)+1) || (dayPointer % 7 == (startAt * -1))) {  // 일요일, 토요일일때
            sHTML += "<div style='"+sStyle+"' onclick='javascript:parent.dateSelected="+datePointer + ";parent.closeCalendar();'> <font color=red>" + datePointer + "</font> </div>";
        } else {
            sHTML += "<div style='"+sStyle+"' onclick='javascript:parent.dateSelected="+ datePointer + ";parent.closeCalendar();'>" + datePointer + "</div>";
        }
        sHTML += "";

        if((dayPointer+startAt) % 7 == startAt) {
            sHTML += "</tr><tr height=16>";
            intWeekCount ++;
        }
    }
    sHTML += "</tr>";
    sHTML = sHTML.replace("<tr height=16></tr>", "");
    if (((dayPointer+startAt) % 7) == 0) intWeekCount--;
    oPopup.document.getElementById("content").innerHTML = sHTML; 
    //////// 셀릭트 월 선택
    oPopup.document.getElementById("spanMonth").innerHTML = " " +    monthName[monthSelected] + " <input type='button'  id='changeMonth'value='▼'  class='cnj_input2' onfocus='this.blur()' onMouseover=\"this.className='cnj_input3'\" onMouseout=\"this.className='cnj_input2'\">"

    //////// 셀릭트 년도 선택
    oPopup.document.getElementById("spanYear").innerHTML =    " " + yearSelected    + "년 <input type='button'  id='changeYear'' value='▼'  class='cnj_input2' onfocus='this.blur()' onMouseover=\"this.className='cnj_input3'\" onMouseout=\"this.className='cnj_input2'\">"

    //alert(intWeekCount);
    var popHeight;
    if (intWeekCount == 6)
        popHeight = 195;
    else
        popHeight = 177;
    oPopup.show(cleft, ctop, 198, popHeight, document.body);
}

function popUpCalendar(ctl, ctl2, format) {
    var leftpos = 0;
    var toppos = 0;
    var leftscroll = 0;
    var topscroll = 0;

    if(bPageLoaded) {
        ctlToPlaceValue    = ctl2;
        dateFormat=format;
        formatChar = " ";
        aFormat    = dateFormat.split(formatChar);

            if(aFormat.length<3) {
                formatChar = "/";
                aFormat    = dateFormat.split(formatChar);

                if(aFormat.length<3) {
                    formatChar = ".";
                    aFormat    = dateFormat.split(formatChar);

                    if(aFormat.length<3) {
                        formatChar = "-";
                        aFormat    = dateFormat.split(formatChar);

                        if (aFormat.length<3) {
                            formatChar="";
                        }
                    }
                }
            }
            tokensChanged =    '0';

            if(formatChar != "") {
                aData =    ctl2.value.split(formatChar);

                for(i=0;i<3;i++) {
                    if ((aFormat[i]=="d") || (aFormat[i]=="dd")) {
                        dateSelected = parseInt(aData[i], 10);
                        tokensChanged++;
                    } else
                    if((aFormat[i]=="m") || (aFormat[i]=="mm")) {
                        monthSelected =    parseInt(aData[i], 10) - 1;
                        tokensChanged++;
                    } else
                    if(aFormat[i]=="yyyy") {
                        yearSelected = parseInt(aData[i], 10);
                        tokensChanged++;
                    }else
                    if(aFormat[i]=="mmm") {

                        for(j=0; j<12;    j++) {
                            if (aData[i]==monthName[j]) {
                                monthSelected=j;
                                tokensChanged++;
                            }
                        }
                    } else
                    if(aFormat[i]=="mmmm") {
                        for(j=0; j<12;    j++) {
                            if (aData[i]==monthName2[j]) {
                                monthSelected=j;
                                tokensChanged ++;
                            }
                        }
                    }
                }
            }

            if((tokensChanged!=3) || isNaN(dateSelected) || isNaN(monthSelected) || isNaN(yearSelected)) {
                dateSelected = dateNow;
                monthSelected =    monthNow;
                yearSelected = yearNow;
            }
            odateSelected=dateSelected;
            omonthSelected=monthSelected;
            oyearSelected=yearSelected;

            aTag = ctl;
            bTag = ctl;
           
            do {
                aTag = aTag.offsetParent;
                leftpos    += aTag.offsetLeft;
                toppos += aTag.offsetTop;
                leftscroll    += aTag.scrollLeft;
                topscroll += aTag.scrollTop;   
       
            } while(aTag.tagName!="BODY");
           
            cleft =    fixedX==-1 ? (ctl.offsetLeft + leftpos) - leftscroll : fixedX;
            ctop = fixedY==-1 ?    (ctl.offsetTop + ctl.offsetHeight + toppos) - topscroll :    fixedY;
            constructCalendar (1, monthSelected, yearSelected);

            bShow = true;
            ctlNow = ctl;
        }
    }

init();
</script>

<input type="button" value="달력" onclick="popUpCalendar(this, txtDate, 'yyyy-mm-dd')">
<input type="text" name="txtDate" readonly>

Posted by 1010
반응형

디자인이 어디갔지?

왜 이 홈페이지에 스타일이 사라졌는지 궁금하다면, Annual CSS Naked Day 사이트를 방문해 주세요. 한국어 설명도 있습니다.



접근성을 해치지 않는 자바스크립트의 사용

신현석

2006년 5월

자바스크립트에 대한 잘못된 생각

자바스크립트 없이는 개발을 할 수 없다?

많은 개발자들이 자바스크립트가 없이는 개발을 할 수 없다고 생각한다. 그만큼 자바스크립트를 일상적으로 많이 사용하고, 자바스크립트에 대해서 잘못 오해하고 있는 부분이 많다는 것이다. 자바스크립트는 클라이언트 환경에서 작동하기 때문에 핵심로직에 사용해서는 안된다. 핵심적인 로직은 서버사이드 언어로 처리를 하고 자바스크립트는 그 옆에서 UI구성을 위해서 도와주기만 해야 한다. 바꿔 말하면 자바스크립트가 없어도 핵심 로직은 작동을 해야 한다. 먼저 자바스크립트없이 HTML과 서버사이드 언어만으로 완벽하게 작동 할 수 있게 개발을 끝낸 후 자바스크립트를 이용해서 좋은 UI나 유효성 검사 등을 하는 부분을 추가 하는 순서로 만들어야 한다. 만약 이를 어기고 자바스크립트를 기능의 일부로 사용하면 접근성이 떨어지는 것 뿐만 아니라 보안도 떨어지고 데이터의 무결성도 보장되지 않는다.

자바스크립트가 작동하지 않는 환경도 고려를 해 줘야 하는가?

자바스크립트가 작동하지 않는 환경이 일반적인 상황은 아니지만 스크립트를 사용할 수 없는 환경에 대한 고려는 반드시 필요하다. 실제로 브라우져에 따라서는 자바스크립트 버젼이 다를 수 있고 개발 환경에서는 잘 작동하던 기능이 어떤 사용자 환경에서는 작동하지 않을 수도 있다. 그리고 사용자 중에서도 여러 이유로 스스로 자바스크립트 사용을 중지하고 사용하는 경우도 있다. 자바스크립트를 사용하지 않아도 핵심 기능을 구현할 수 있음에도 불구하고 불필요한 자바스크립트를 사용하여 접근성을 떨어뜨리는 것이 올바른 페이지 제작 방법은 아니다.

서버 부하를 줄이기 위해서 자바스크립트로만 유효성 검사를 한다?

자바스크립트를 이용해서 서버의 부하를 줄일 수 있다는 것은 많은 사람들이 알고 있을 것이다. 자바스크립트로 선처리를 행함으로서 네트웍이나 서버의 처리를 감소시킨다는 것인데 이것을 잘못 이해하여 자바스크립트만으로 유효성을 체크하는 것이 좋다고 생각하는 사람들이 있다. 자바스크립트로 선처리를 한결과물을 그대로 믿으면 안된다. 사용자측으로 부터 넘오온 모든 값은 그 값의 유효성을 완전히 보장할 수 없기 때문에 서버측에서도 유효성 체크를 해 줘야만 한다. 이것은 서버의 부하를 높이는 것 이전에 자료의 무결성을 보장하는 중요한 과정이다. 자바스크립트를 거치지 않고 서버에 임의로 변조된 값을 보내는 일은 아주 쉬운 일이다.

자바스크립트를 사용하지 않으면 UI가 불편해 진다?

자바스크립트를 이용해서 RIA나 좋은 UI를 만들 수 있는 것은 사실이지만 웹환경을 이해하고 일반적인 웹 인터페이스를 이용해서 만드는 것이 더 좋은 UI를 제공할 수 있다. 사용자 친화적인 UI에 대한 고민을 해야지 자바스크립트를 사용했다고 좋은 UI가 나오는 것은 아니다. 실제적으로 가장 사용자가 이해하기 쉬운 UI는 사용자 OS나 브라우저에서 기본적으로 제공하는 컨트롤 인터페이스를 그대로 사용하는 것이고 이는 자바스크립트 없이도 충분히 가능하다.

자바스크립트는 사용자 환경에 내려보내지고 사용자의 브라우져에서 실행이 되기 때문에 이에 의존해서 프로그램을 만들게 되면 보안, 접근성에 문제가 생기기 쉽다. 이러한 자바스크립트의 특징을 정확히 이해하지 못한 잘못된 개발 방법이나 상식들 때문에 자바스크립트가 오용되고 있는 경우가 많다. 자바스크립트는 어디까지나 보조적인 수단이라는 것을 이해하고 핵심적인 기능을 해치지 않는 한도에서 사용하는 것이 무엇보다 중요하다.

자바스크립트 선언

<script language="Javascript">
//code
</script>

자바스크립트는 <script> 엘리먼트로 선언을 한다. 모든 <script>엘리먼트는 type을 명시해 주어야 하고 자바스크립트의 type은 "text/javascript" 이다. 많은 경우 language 만을 선언해서 자바스크립트버젼을 명시하는데 반드시 type도 같이 명시를 해 주어야 한다.

<script type="text/javascript">
//code
</script>

<a>의 href 속성과 자바스크립트의 사용

href는 Hypertext REFerence의 약자이다. 다시 말해서 hypertext의 위치를 나타내는 uri를 그 값으로 갖는다. 하지만 많은 경우 이 href안에 "javascript:myFunction()"과 같이 잘못된 구문을 이용하는 것을 볼 수 있다. 이와 같이 href안에 잘못된 값이 들어가게 될 경우, 북마크나 새창, 새탭으로 열기 등의 href 관련된 브라우저의 기능들이 정상적으로 작동하지 않게 된다. 따라서 href안에는 항상 uri가 들어가도록 하고 자바스크립트 적용은 onclick과 같은 이벤트 속성을 이용해야 한다.

의미 없는 href 값을 사용한 경우

사용자의 링크 클릭이 링크와 관련이 있고 이를 자바스크립트를 이용해서 처리를 하야 하는 경우가 있다면 우선은 자바스크립트를 빼고도 페이지의 이동을 할 수 있게 href에 적절한 값을 넣어 주어야 한다. 이와 같은 경우로 탭메뉴를 들 수 있다. 탭메뉴의 경우 탭을 누르면 해당 탭과 관련있는 컨텐츠를 보여주는 식으로 작동하게 된다. javasript가 없다면 탭을 클릭했을 때 해당 컨텐츠로 이동을 하는 식으로 구현 되면 된다. href 안의 값으로 페이지 안에서의 해당 컨텐츠 앵커 주소를 넣는 것으로 간단히 구현 된다.

<a href="#notice-list"><img src="notice-tab.gif" alt="Notice" /></a>

그리고 이 마크업을 기본으로 하여 이벤트 속성으로 원하는 기능을 넣어주면 된다.

<a href="#notice-list" onclick="showNoticeTab(); return false;"><img src="notice-tab.gif" alt="Notice" /></a>

onclick으로 탭을 보여준 후 false를 리턴하여 해당 앵커로 이동하지 않도록 처리 한다. 자바스크립트가 작동을 할 때에는 클릭하면 정상적으로 탭으로 작동을 할 것이고, 그렇지 않을 경우에는 해당 컨텐츠로 이동을 하여 높은 접근성을 유지할 수 있다.

만약 자바스크립트가 링크와 관련이 없는 경우에는 <a>태그를 사용해서 스크립트를 적용하면 안된다. 보통 특정 효과를 주는 것이 이러한 것에 해다하게 되는데 이 경우 자바스크립트가 작동을 하지 않아도 컨텐츠 이해에 크게 문제가 되지 않는 경우이다.

<img src="button.gif" style="cursor: pointer;" onclick="myAction()" />

효과를 위한 자바스크립트는 단순히 onclick을 이용해서 적용을 하고 <a>를 사용하지 않는다. 그리고 사용자가 마우스 포인터를 올렸을 때 손모양으로 나오는 것은 스타일로 처리하면 된다.

팝업창을 열 때(window.open)

<img src="openWindow.gif" onclick="window.open('popup.html', '', 'widht=300,height=200')">
<a href="#"><img src="openWindow.gif" onclick="window.open('popup.html', '', 'widht=300,height=200')"></a>

href에 #과 같은 의미 없는 값을 넣거나 onclick 안에 경로를 처리하는 경우가 있는데 팝업창은 링크이고 페이지가 별도로 존재 하기 때문에 <a>를 이용해서 기능을 구현하고 href엔느 해당 팝업의 경로를 넣어야 한다.

<a href="popup.html" onclick="window.open(this.href, 'popupName', 'width=300,height=200'); return false;"><img src="openWindow.gif"></a>

이럴 경우 사용자가 자신의 의도 대로 팝업창을 새창, 새탭 등으로 열 수 있고 심지어 즐겨 찾기도 할 수 있다.

자바스크립트를 이용한 페이지 이동

웹사이트를 이용하다 보면 폼에서 값을 입력하고 서밋을 하는 순간 "따다다닥" 하는 식으로 클릭을 여러번 한 것과 같은 소리가 나는 경우를 접하게 된다. 프로세스가 여러페이지에 걸쳐서 일어나게 되는데 이 처리를 자바스크립트로 처리를 해서 이러한 현상이 발생을 하게 된다.

<script type="text/javascript">document.location.href="redirection.html";</script>

위와 같이 페이지를 이동 하거나 아래와 같이 <form>을 이용해서 값을 넘기는 경우가 이러한 경우이다.

<form name="login_form">
	<input type="hidden" name="user_id" value="myid" />
	<input type="hidden" name="user_pwd" value="mypassword" />
	<input type="hidden" name="redirect_url" value="http://mysite.com/login/" />
	<input type="hidden" name="somevalue" value="blahblah" />
	...
</form>
<script type="text/javascript">
f = document.forms.login_form;
f.action = "http://login.oursite.com/login/";
...
f.submit();
</script>

심한 경우 아래와 같이 전혀 의미 없는 폼을 이용하기도 한다.

<form method="post" name="sg_form" action="http://www.qubi.com/" target="_top">
</form>
<script> sg_form.submit(); //3</script>

위와 같은 페이지들은 html 문법상 오류가 있는 페이지 들이고 이 때문에 작동이 안 될 수도 있다. <form>엘리먼트나 <script>엘리먼트는 상위에 <body>나 <head>엘리먼트가 있어야 하는데 위와 같은 경우 이러한 엘리먼트가 없기 때문에 html로 해석이 안되어 스크립트가 작동 되지 않거나 값이 넘어가지 않을 수도 있다. 그리고 <form>에 submit <input>이 없기 때문에 자바스크립트로 submit이 일어나지 않을 수도 있다.

이와 같이 페이지를 이동하거나 값을 넘길 필요가 있을 때 자바스크립트에 의존해서 이를 처리하게 되면 클라이언트의 환경에 따라서 동작이 실패할 수 있다. 따라서 이러한 처리는 자바스크립트에서 처리 하지 말고 서버 측에서 http헤더 정보를 이용해서 처리해야 한다.

이러한 중간과정에서의 처리를 서버측에서 모두 처리 하는 것이 가장 바람직 하지만 어쩔 수 없이 사용을 해야할 경우에는 - 그럴 경우가 많지는 않겠지만 기존의 호환성을 위해서 - DTD선언이나 <html> 루트 엘리먼트, <head>, <body>와 같이 필수 엘리먼트들이 존재하는 완결된 페이지를 사용 하도록 하고, 자바스크립트가 작동하지 않는 경우를 위해서 <form>에 submit버튼도 제공을 하고, 결과 메세지도 alert외에 일반 text와 <a>를 이용한 링크를 제공하도록 해야 한다.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr" />
<title>Redirect</title>
</head>
<body>
<script type="text/javascript">
/*
 some processes...
*/
alert('이래저래한 이유로 다시 돌아 갑니다.');
document.location.href="redirection.html";
</script>
<p><a href="redirection.html">이래저래한 이유로 다시 돌아 갑니다.</a></p>
</body>
</html>

charset이 없는 경우 브라우져의 기본 설정으로 alert이 작동하기 때문에 브라우져의 기본 설정이 ko-kr이 아닌 경우 한글이 깨지게 된다. 문서의 mime-type도 text/html인지 확인해야 한다.

<form>에서의 자바스크립트 사용

일반적으로 <form>은 사용자가 입력한 값을 서버측에 전달하는 역할을 하고 그 전달은 <form>의 submit 기능을 통해서 이루어 진다. 이러한 폼을 구현 할 때에 일반적으로 자바스크립트를 사용하는 경우가 많다.

submit

폼은 그 자체적으로 값을 보내는 서밋기능을 제공하고 있다. <input type="submit" />이나 <input type="image" />이 서밋기능을 하는 컨트롤인데 폼의 값 유효성 체크를 하는 과정에서 이러한 폼의 자체적인 서밋기능을 이용하지 않고 자바스크립트로 폼 서밋을 하는 경우가 있다.

<script type="text/javascript">
function submitForm() {
	loginForm.submit();
}
</script>
<form id="loginForm" name="loginForm" action="">
	User Id <input type="text" name="loginId">
	User Password <input type="password" name="loginPassword"><br>
	<img src="login.gif" onclick="submitForm()">
</form>

위와 같은 경우 폼에 서밋기능이 없기 때문에 브라우져에 따라서 script로 서밋이 안되는 경우도 있고 서밋 대신에 이미지가 들어가 있기 때문에 의미적으로도 맞지 않게 된다. 따라서 폼을 제작할 때에는 반드시 서밋기능을 <input>을 이용해서 제공해야 한다.

<form id="loginForm" name="loginForm" action="">
	<p>
		<label for="loginId">User Id</label>
		<input type="text" id="loginId" name="loginId" /><br />
		<label for="loginPassword">User Password</label>
		<input type="password" id="loginPassword" name="loginPassword" />
	</p>
	<p>
		<input type="image" src="login.gif" alt="Login" />
	</p>
</form>

많은 경우 <html>제작 과정에서 서밋을 <img>로 넣는 경우가 있는데 이 경우 이를 그냥 사용하면 안되고 적절한 <input>으로 바꾸어서 사용해야 한다.

validation

클라이언트 측에서 자바스크립트를 이용한 유효성 검증은 <form>의 서밋 이벤트를 캐치하는 방식으로 구현해야 하고 자바스크립트가 폼을 서밋하는 방식을 사용하면 안된다.

<script type="text/javascript">
function submitForm() {
	if (!loginForm.loginId.value) {
		alert("아이디를 넣어주세요.");
		loginForm.loginId.focus();
	} else if (!loginForm.loginPassword.value) {
		alert("비밀번호를 넣어주세요.");
		loginForm.loginPassword.focus();
	} else {
		loginForm.submit();
	}
}
</script>
<form id="loginForm" name="loginForm" action="">
	아이디 <input type="text" name="loginId">
	비밀번호 <input type="password" name="loginPassword"><br>
	<img src="login.gif" onclick="submitForm()">
</form>

위와 같은 경우 자바스크립트만을 이용해서 폼을 서밋하고 있기 때문에 자바스크립트가 없이 HTML만으로는 기능이 작동하지 않는다.

<script type="text/javascript">
function submitForm(formEl) {
	//TrimAll(formEl);

	var errorMessage = null;
	var objFocus = null;

	if (formEl.loginId.value.length == 0) {
		errorMessage = "아이디를 넣어주세요.";
		objFocus = formEl.loginId;
	} else if (formEl.loginPassword.value.length == 0) {
		errorMessage = "비밀번호를 넣어주세요.";
		objFocus = formEl.loginPassword;
	}

	if(errorMessage != null) {
		alert(errorMessage);
		objFocus.focus();
		return false;
	}
	return true;
}
</script>

<form id="loginForm" name="loginForm" action="" onsubmit="return submitForm(this)">
	<label for="loginId">아이디</label> <input type="text" id="loginId" name="loginId" />
	<label for="loginPassword">비밀번호</label> <input type="password" id="loginPassword" name="loginPassword" /><br />
	<input type="image" src="login.gif" alt="Login" />
</form>

이와 같이 onsubmit 이벤트를 이용해서 폼의 유효성을 체크하고 그 결과를 true나 false로 보내줌으로써 폼이 스크립트에 따라서 서밋을 진행하거나 멈출 수 있고, onsubmit 이벤트가 발생하지 않아도 사용자는 폼을 사용할 수 있기 때문에 접근성이 높아지게 된다.

게시판 등에서 기능을 모두 자바스크립트로 하는 경우

게시판에서 페이지의 이동을 자바스크립트만으로 하는 것을 많이 볼 수 있다. 아래와 같이 사용자 인풋이 없는 빈 <form>을 하나 만들고 이것과 자바스크립트를 이용해서 글을 읽거나 페이지를 이동하는 것이다.

<form method="post" name="vars">
	<input type="hidden" name="articleId" value="23" />
	<input type="hidden" name="page" value="3" />
	<input type="hidden" name="keysord" value="" />
	<input type="hidden" name="searchType" value="" />
	<!-- 등등 -->
</form>

...

<a href="javascript:ArticleRead()">글읽기</a>
<a href="javascript:GoList()">리스트 보기</a>

url이 간단해 지고 다루기 쉽다는 이유로 이러한 방식으로 개발을 하는 경우가 많은 것 같은데 절대로 사용해서는 안되는 방식이다.

우선 위와 같이 모든 기능을 자바스크립트를 이용해서 구현을 하게 되면 자바스크립트 오류가 있거나 핸드폰과 같이 자바스크립트가 정상적으로 작동 하지 않는 상황에서는 접근을 할 수 없게 된다. 또한 모든 변수를 post를 통해서 전달하기 때문에 url에 표시가 되지 않고 해당 페이지를 따로 북마크 한다든지 저장을 할 수가 없게된다. 게시판의 경우 해당 게시물로의 접근을 쉽게 해 주어야 하는데 사용자가 url을 알 수 없게 함으로써 접근을 원천적으로 막게 된다.

자바스크립트를 이용하지 않고도 <a>와 url만으로도 작동 가능한 페이지를 만들고 QueryString을 효율적으로 다루는 방법을 모색하여 개발을 진행하는 것이 가장 좋은 방법이다.

마치며

본인이 웹사이트 개발을 하면서 접할 수 있었던 몇몇 잘못된 자바스크립트 사용 예를 적어 보았다. 그런데 놀라운 것은 이러한 개발 방식을 초보부터 어느정도 경력이 된 개발자들 까지 아무런 고민 없이 사용하고 있다는 것이다. 책이 잘못된 것인지 교육이 잘못 된 것인지 정확히 근원을 알 수는 없지만 많은 개발자들이 웹이 가지고 있는 기본적은 특성을 무시한채 잘못된 방법을 이용하여 개발을 하고 있는 것이 사실이다. 그리고 또 초보 개발자들은 HTML을 잘 모르기 때문에 이러한 개발 방식을 아무 고민 없이 그냥 받아들이고 있는 것이 사실이다.

브라우저 접근성을 가장 크게 낮추고 있는 것이 바로 이 잘못된 자바스크립트의 사용이다. 부디 조금이라도 많은 개발자들이 링크에 기초한 웹의 특성을 이해하고 접근성 높은 웹사이트, 웹 어플리케이션을 구축 하기를 바라는 바이다.

다운로드 : accessible-javascript.pdf(pdf 225KB)



Posted by 1010
반응형

오라클에서 rownum 은 쿼리가 실행될 때 결과 레코드에 번호를 나타내어 주는 필드이다.

물론 table 을 만들 때 rownum 을 만들어줄 필요는 없다.

어떠한 테이블이라도 "select rownum from boardtable" 의 형태로 쿼리를 날리면 레코드에

번호컬럼이 생기는 것을 볼수 있다.

따라서 페이징을 위한 쿼리에서 우리는 rownum 10 보다 크고 20 보다 작은

이런 식의 조건을 주어 원하는 범위의 레코드만 쿼리 할수 있다.

Select * from boardtable where rownum > 10 and rownum <=20

 

위와 같이 쿼리 하면 어떨가? 결과가 하나도 않나올 것이다. 왜냐하면 쿼리가 실행될 때

Where 부분이 먼저 실행한다. Select 하기 전에 rownum 이 발생하지 않기 때문에

rownum 할 데이터가 없어서 아무 값도 가져오지 못하게 되는것이다.

다시 쿼리를 수정하게 되면 다음과 같다.

Select 서브 쿼리를 날려서 먼저 데이터를 가져온후에 rownum 을 하는것이다.

Select * from (select rownum numrow, boardtable from boardtable)

Where numrow > 10 and numrow <= 20

 

여기에서 문제가 다 해결된건 아니다. Order by 절을 사용하게 되면 또다른 문제에 직면하게 된다

Select * from (select rownum numrow, boardtable from boardtable order by reg_date desc)

Where numrow > 10 and numrow <= 20

 

실행해 보면 원하는 결과가 나오지 않는 것을 알수있을것이다.

이유는 order by rownum 값을 만드는데 영향을 못주는 것으로 생각된다.

order by 를 지정한다고 해도 rownum 은 최초의 order by 가 없는 상태로 만들어진다.

원하는 형태의 정렬 데이터를 rownum 하고 싶다면 서브쿼리를 order by 절로 날린후

Rownum 을 매기면 된다.

Select rownum numrow, aa.* from (select * from boardtable order by reg_date desc) aa

 

여기에 범위지정 쿼리를 써넣게 되면 어떻게 될까? 위에서 설명한 대로 아무값도 안나오게 된다

Select rownum numrow, aa.* from (select * from boardtable order by reg_date desc) aa

Where numrow > 10 and numrow <= 20

 

이것을 제대로 구현할려면 한번더 select 구문 서브쿼리를 날려야한다.

Select * from (select rownum numrow, aa.* from (select * from boardtable order by reg_date desc) aa ) where numrow > 10 and numrow <= 20

 

이와 같이 하게 되면 서브쿼리를 몇번이나 날리게 되어 데이터 양이 많을경우

퍼포먼스에 문제가 생길수가 있다. 그래서 index hint 절을 사용하여 성능을 향상시켜준다.

Index order by 구문에 나오는 reg_date 를 주면될것이다.

Create unique index  idx_board_reg_date on boardtable (reg_date, idx)

Posted by 1010
반응형

자바스크립트 객체의 종류와 설명이다
document : 현재 웹 페이지의 본문을 나타낸다. 이 객체를 사용하면 링크(link), 이미지, 앵커(anchor) 등과
                같은 웹 페이지의 모든 구성요소에 접근할 수 있다.

history : 웹 브라우저에서 현재 페이지를 열기 전까지의 사이트 기록을 같고있다. 이객체를 사용하면,
            히스토리(history) 목록을 통해 이전 페이지 또는 다음 페이지로 이동할 수 있다.

location : 현재 웹 페이지의 위치에 대한 URL, 도메인이름, 경로, 서버포트 등의 정보를 갖는다.

navigator : 실제로 브라우저 자체를 가리킨다. 이 객체를 사용하면, 사용중인 브라우저의 종류를 알아낼 수 있다.

window : 현재 브라우저 창을 가리키며, 여러가지 강력한 메소드들을 제공한다.
             Internet Explorer에서는 event라는 하위 객체를 사용하여 이벤트를 처리할 수 있다.

■ location 객체 프로퍼티

href 문서의 URL 주소 위 주소 전체
host 호스트 이름과 포트 http://www.codewiz.co.kr:80
hostname 호스트 컴퓨터이름 http://www.codewiz.co.kr
hash 앵커이름 #top
pathname 디렉토리 이하 경로 /column2/list.asp
port 포트번호 부분 80
protocol 프로토콜 종류 http:
search URL 조회부분 table=table30&page=2

location 객체 메서드
eval() 문자열을 숫자로 바꿈
toString() 오브젝트를 문자열로 바꿈
reload() 현재 문서를 다시 읽어옴
replace() 현재 문서를 다른 URL 문서로 바꿈
valueOf() 오브젝트 값을 표시
toSource() 오브젝트 값을 문자열로 표시

■ 활용예제

<script language="javascript">
// URL을 이동시킴
location.href= http://codewiz.com
//location.href= "login.html"
</script>
<script language="javascript">
alert("회원가입을 하시겠습니까?")
location.href= "member.html"
</script>
<script language="javascript">
// 연 창의 URL 이동
opener.location.href= "member.html"
</script>
<script language="javascript">
// 부모창 지정프레임의 URL 이동
parent .frame1.location.href= "member.html"
</script>
<script language="javascript">
// 전체창에 새 페이지 열기
top.location.href= "index.html"
</script>


활용예제이다.
// 역슬레쉬로 구분해서 배열을 만든다
var path = parent.frames["input"].location.pathname.split('/');
// 배열의 마지막 요소의 값을 저장한다
var temp = "";
temp = path[path.length - 1];


출처 : http://mainia.tistory.com/entry/현재페이지를-알아오는-방법

Posted by 1010
반응형

전체 쿠키 정보를 Text 로 출력한다 . 모든 쿠키에 대한 정보를 알아볼려면  document.cookie 를 호출하면 된다. 집어 넣는 곳은 cookieOut 이라는 DIV 내에 Text 를 출력하는  로직이다.
// 모든 쿠키출력
function viewCookie()
{
   if( document.cookie.length > 0 )
      cookieOut.innerText = document.cookie;
   else
      cookieOut.innerText = "저장된 쿠키가 없습니다.";
}
// 출력화면
<DIV id = "cookieOut"></DIV>


저장된 쿠키값을 쿠키명으로 검색해서 넘겨주는 함수이다.
// param : 쿠키명
// return : 쿠키값
function getCookie( cookieName )
{
   var search = cookieName + "=";
   var cookie = document.cookie;

   // 현재 쿠키가 존재할 경우
   if( cookie.length > 0 )
   {
       startIndex = cookie.indexOf( cookieName );// 해당 쿠키명이 존재하는지 검색후 위치정보를 리턴.

       if( startIndex != -1 ) // 존재한다
      {
         startIndex += cookieName.length;// 값을 얻어내기 위해 시작 인덱스 조절
         endIndex = cookie.indexOf( ";", startIndex );// 값을 얻어내기 위해 종료 인덱스 추출
         if( endIndex == -1) endIndex = cookie.length; // 만약 종료 인덱스 못찾으면 쿠키 전체길이로 설정

         return unescape( cookie.substring( startIndex + 1, endIndex ) );// 쿠키값을 추출하여 리턴
      } else {
         return false; // 존재하지 않을때
      }
   } else {
      return false; // 쿠키 아예없을때
   }
}

쿠키값을 설정한다. 파라미터로는 쿠키명, 쿠키값, 쿠키날짜를 넘긴다
function setCookie( cookieName, cookieValue, expireDate )
{
   var today = new Date();
   today.setDate( today.getDate() + parseInt( expireDate ) );
   document.cookie = cookieName + "=" + escape( cookieValue ) + "; path=/; expires=" +                
           today.toGMTString() + ";"
}


쿠키명을 넘겨 해당하는 쿠키를 삭제한다
function deleteCookie( cookieName )
{
   var expireDate = new Date();
 
   //어제 날짜를 쿠키 소멸 날짜로 설정한다.
   expireDate.setDate( expireDate.getDate() - 1 );
   document.cookie = cookieName + "= " + "; expires=" + expireDate.toGMTString() + "; path=/";
}



Posted by 1010
반응형
부모창에서 자식 새창으로 submit 데이타를 보낼때 자식창에선 그것을 데이타 크기에 맞게
늘렸다 줄였다 할수있다. 이것은 프린트 공통 화면을 만들때 유용하게 쓰인다.
내용은 화면이 시작되고 나서 밑쪽에 initWindow 함수가 실행되게 된다.

<html>
<head>
#parse("common/common_head.vm")
<link href="${rc.contextPath}/css/ord.css" rel="stylesheet" type="text/class" />
<script language="JavaScript">
<!--
 // submit 넘어오는 html 데이타를 화면 크기에 맞게 배치해준다.
 function initWindow(win){
    var winBody = win.document.body;
    // 새창의 사이즈에 더해줄 marginWidth 와 marginHeight
    var marginHeight = parseInt(winBody.topMargin)+parseInt(winBody.bottomMargin);
    var marginWidth = parseInt(winBody.leftMargin)+parseInt(winBody.rightMargin);
    // 새창의 사이즈 설정
    var wid = winBody.scrollWidth + (winBody.offsetWidth - winBody.clientWidth) + marginWidth - 5;
    var hei = winBody.scrollHeight + (winBody.offsetHeight - winBody.clientHeight) + marginHeight + 17;
    // 사이즈 재조정
    win.resizeTo(wid, hei);
 }
 
 var initBody; // 프린트 실행전 내용이 담기는 공간
 function beforePrint(){
    initBody = document.body.innerHTML;
    document.body.innerHTML = resultPrint.innerHTML;
 }
 function afterPrint(){
    document.body.innerHTML = initBody;
 }
 function printArea(){
    window.print();
 }
 window.onbeforeprint = beforePrint; // 프린트 하기 이전의 내용실행 해서  body 의 내용을 바꾼다.
 window.obafterprint = afterPrint; // 프린트 후 함수를 실행하여 이전에 저장해놨던 정보로 내용을 바꾼다.
//-->
</script>
</head>
<body>
 <table width="100%" border="0" cellspacing="0" cellpadding="10">
   <tr>
     <td valign="top">
     <DIV id="resultPrint">
      $!{print}
     </DIV>
     </td>
   </tr>
   <tr>
    <td><a href="javascript:printArea();"> 프린트 하기 </a></td>
     </tr>
 </table>
 <script language='javascript'>
 <!--
  initWindow(this);
 //-->
 </script>
</body>
</html>

Posted by 1010
반응형
javascript 가 복잡해지면 에러를 찾기가 만만치 않다. 그래서 브라우저에 포함된 디버깅툴이 있다면
상당히 프로그램하기에 편할뿐더라 생산성 또한 높일수 있을것이다.
파이어폭스 플러그인 Firebug 의 콘솔 API 와 유사한데 IE 사용할수 있다.
Companion.JS 이며 http://www.my-debugbar.com/wiki/CompanionJS/Homepage 에서 다운받을수있다.

이프로그램을 먼저 설치하기 전에 Microsoft Script Debugger 를 먼저설치한다.
http://www.microsoft.com/downloads/details.aspx?familyid=2f465be0-94fd-4569-b3c4-dffdf19ccd99&displaylang=en

다음은 스크립트 디버딩사용안함 을 체크해제한다.

사이트에 가서 다운로드 한다.

설치를 하게 되면 익스플로어에 다음과 같이 설치가 된다.

아래 그림과 같이 디버깅 창이 나오게 된다.
Posted by 1010
반응형

브라우저의 종류에 따라서 text 값을 바꾸는 방식이 모두다 적용되는것은아니다.
아래 내용은 IE6, Netscape 6.2 and 7, Firefox 1.04,  Opera 8 on the PC. 동일하게 적용되는
과정을 알아본다.

<input type="button"> 선언된 버튼의 value 값을 바꿔보는데
첫번째 예제는  getElementById("ID").value 변수로 값을 바꾸는 방식이다

<input type="button" value="Button Text" id="myButton1"></input>
document.getElementById("myButton1").value="New Button Text";

위의 방식은 IE6 에서는  "Unknown Runtime Error; Netscape 7 에서는  won't change the text
에러가 날것이다. 그래서 두번째는 innerHTML 을 사용해서 바꾸는 방식이다.

document.getElementById("myButton1").innerHTML="New Button Text";

다음은 버튼 태그 사이의 text  값을 바꿔본다.
innerHTML 을 사용해서 바꾸었다.

document.getElementById("myButton2").innnerHTML=  "New Button Text using innerHTML";
<button type="button" id="myButton2">Button Label</button>

위의 방식은 Netscape 6.2 and 7.02 에서 쓰레기 값을 가져오게 되어 에러가 발생한다.
그래서 childNodes  를 아래와 같이 사용한다.
이와 같이 값을 바꾸고자 할때 버전에 구애받지 않게 적용하고 싶을 것이다.
아래의 함수는 처음에 childNodes 바꿀수 있는지 체크해서 시도하고 그게 안된다면 value 로 적용한다
그리고 그것도 안된다면 innerHTML 을 사용하는 전천후 함수이다.

<SCRIPT LANGUAGE="JavaScript">

<!--

function replaceButtonText(buttonId, text)

{

  if (document.getElementById)

  {

    var button=document.getElementById(buttonId);

    if (button){

      if (button.childNodes[0]){

        button.childNodes[0].nodeValue=text;

      }

      else if (button.value){

        button.value=text;

      }

      else //if (button.innerHTML){

        button.innerHTML=text;

      }

    }

  }

}

//-->

</SCRIPT>

replaceButtonText('myButton1', 'new button text');

Posted by 1010
반응형

<script language="javascript">

<!--

function add(){

   var target = document.getElementById("dynamicTable");

   var currentRowIndex = target.rows.length;

   var row = target.insertRow(-1);

   var cell = row.insertCell(-1);

   cell.innerHTML = "<input type='text' name='point"+ currentRowIndex +

         "' size='5' maxlength=='5' value='20'>&nbsp;&nbsp;" +

         "<select name='scope" + currentRowIndex + "'>" +

         "<option>초과</option>" +

         "<option>이상</option>" +

         "<option>이하</option>" +

         "<option>미만</option>" +

         "</select>";

}

 

function checkToggle(form){

   var i=1;

   var isDisabled = (form.auto.checked) ? true : false;

   while(true){

      var scopeElement = form["scope" + i];

      var pointElement = form["point" + i++];

      if (scopeElement){

          scopeElement.disabled = isDisabled;

          pointElement.disabled = isDisabled;

      }else{

          break;

      }

   }

}

//-->

</script>

</head>

 

<body>

<form name="form">

   <input type="checkbox" name="auto" onclick="checkToggle(this.form)"> Disabled 된다

   <input type="button" value="add" onclick="add()">행추가

   <table id="dynamicTable" border="0" cellpadding="5" cellspacing="1" align="center">

     <thead>

       <tr align="center">

         <td width="130">점수</td>

       </tr>

     </thead>

     <tbody>

        <tr align="center">

           <td colspan="4">

      <input type="text" name="point1" size="5" maxlength="5" value="20">

      &nbsp;&nbsp;

              <select name="scope1">

                 <option>초과</option>

                 <option>이상</option>

                 <option>이하</option>

                 <option>미만</option>

              </select>

            </td>

        </tr>

     </tbody>

  </table>

</form>

</body>
Posted by 1010
반응형
javascript 에서 input 값에 숫자이외의 글을 넣었을때 더이상 입력이 되지 않도록 막는 소스이다.

<script language="JavaScript">
function checkForNumber() {
  var key = event.keyCode;
  if(!(key==8||key==9||key==13||key==46||key==144||
      (key>=48&&key<=57)||key==110||key==190)) {
      event.returnValue = false;
  }
}
</script>

javascript 함수는 위의 것을 쓰면되고 Input 에 key 입력시 event 객체가 가로채서 그 내용을
분석한후 event.returnValue = false 리턴하게 되면 더 이상 키의 값을 입력할수 없게 해준다.
이것을 활용하여 여러가지 입력형태의 제한을 만들어서 사용하면 유용할 것이다

<input type="text" name="aaa" style="ime-mode:disabled;" onkeypress="checkForNumber();">
Posted by 1010
반응형

DOM 객체의 기본 구조도를 알아야한다. 이객체들이 어디에 속해있는지 표를 보고 알아야할것이다


1.
내장함수

(1) 내장메시지 함수

alert("Hello."); confirm("정말로 삭제할껴?"); prompt(메시지, 초기값);

 

(2) 일반내장 함수

isFinite(number) : number한수이면 true, 아니면 false를 리턴

isNaN(value) : value가 순수한 문자이면 true, 숫자형태의 문자이면 false를 리턴

number(obj) : obj를 숫자로 변환하여 리턴

string(obj) : obj를 문자로 변환하여 리턴

eval(수식문자열 또는 Object 문자열) : 수식을 처리한 결과를 리턴, Object로 변환하여 리턴

parseInt(문자열, [진수]) : 문자열을 정수로 변환하여 리턴

parseFloat(문자열) : 문자열을 float-실수형으로 변환하여 리턴

escape(string) : ASCII 스트링을 URL로 인코딩

unescape(string) : ASCII 스트링을 URL로 디코딩

encodeURI(string) : 주어진 문자열을 URI encoding 한다.

decodeURI(string) : 주어진 문자열에서 encoding URI decoding 한다.

encodeURIComponent(string) : 주어진 문자열을 URI encoding 한다.

decodeURIComponent(string) :  주어진 문자열에서 encoding URI decoding 한다.

 

(3) 문자인코딩 함수

encodeURI() / decodeURI() : 다음문자만 인초딩한다  è  ; / ? : @ & = + $ , - _ . ! ~ * ' ( ) #

encodeURIComponent() / decodeURIComponent() :

알파벳과 숫자 Alphanumeric Characters 외의, 대부분의 문자를 모두 인코딩한다.

escape() / unescape() : encodeURI() encodeURIComponent() 의 중간 정도의 범위로 문자 인코딩

 

2. 내장 객체

(1) Object 객체

var book = new Object(); // empty Object --> var book = {};

book.title = "내장객체";

book.author = "kspark";

book.published_date = new Array('2006', '2007');

book.getInformation = function() { return this.title + ", " + this.author; }

 

function DisplayPropertyNames(obj){

             var names = "";

             for( var name in obj ) names += name + "\n";

             alert(names);

             alert(obj.getInformation());

}.

 

(2) Function 객체 : 함수 객체, 객체변수 = new Function([매개변수 리스트], 함수의 처리 내용)

var square = function(x) { return x*x }

var sports = new Object();

sports.soccer = new Function('var name = "soccer"; return name;');

var sum = new Function( "x", "y", "return x+y" );

function execute(){

   alert( "Sports name : " + sports.soccer() );

   alert( "sum : " + sum(5,10) );

}

 

(3) Array 배열 객체

length 속성, join(문자열),reverse(),sort(compareFunction),slice(시작위치,종료위치),concat(배열객체)

var list = new Array();

 

(4) Date 날짜 객체

var date = new Date();

 

getDate, getDay, getFullYear, getHours, getMilliseconds, getMinutes, getMonth,

getSeconds, getTime,  getTimezoneOffset, getUTCDate, getUTCDay,

getUTCFullYear, getUTCHours, getUTCMilliseconds, getUTCMinutes,

getUTCMonth, getUTCSeconds, getYear, parse, setDate, setFullYear, setHours,

setMilliseconds, setMinutes, setMonth, setSeconds, setTime, setUTCDate,

setUTCHours, setUTCMilliseconds, setUTCMinutes,  setUTCMonth, setUTCSeconds,

setYear, goGMTString, toLocaleString, toString, toUTCString, UTC, valueOf

 

(5) String 객체

문자열 조작 메소드

toLowerCase(), toUpperCase(), charAt(인덱스), substring(인덱스1, 인덱스2), slice(인덱스1, 인덱스2),

substr(시작인덱스, 길이), indexOf(문자열), lastIndexOf(문자열), concat(문자열), split(분리자, [개수]), charCodeAt([인덱스]), fromCharCode(숫자)

 

글자 모양을 변경하는 메소드

big(), small(), blink(), bold(), fixed(), italics(), strike(가운데줄), sub(아래첨자),sup(위첨자),

fontcolor(""), fontsize(크기)

 

위치 이동하는 메소드

anchor("책갈피명"), link("이동위치");

 

var str = "Hello! David";

str.slice(6, str.length);   str.link(#david);

 

(6) 수학관련 객체 Math : 각종 수학적 계산을 돕는 Math 객체

Math.PI, Math.sin(x), Math.abs(x), Math.max(x,y)

 

(7) 수치관련 객체 Number

수치 형태의 문자열을 수치 데이터로 변환하는 객체, new Number(수치 형태의 문자열);

var Ten = new Number("10");

 

(8) 논리형 객체 Blooean : 논리 객체, new Boolean(논리값);

 

(9) 스크린 화면 객체 Screen : Screen.availWidth, availHeight(화면의 실제 너비, 높이 ),

Screen.width, height(스크린 실제 너비, 높이), pixelDepth(익스플로워 지원안됨),

colorDepth(사용가능색상수)

 

(10) Event : 이벤트 객체

이벤트 함수의 종류

Abort (onAbort) : 문서를 읽다가 중단시켰을때(브라우저에서 멈춤을 눌렀을때)

Blur (onBlur) : 사용자가 입력을 포커스를 원도우나 입력양식 요소에서 제거했을때

Click (onClick) : 사용자가 입력 양식의 요소나 링크를 클릭 했을때

Change (onChange) : 사용자가 요소의 값을 바꾸었을 때

DblClick (onDblclk) : 사용자가 입력 양식의 요소나 링크를 더블 클릭 했을때

DragDrop (onDragDrop) : 마우스를 드래그 하는 순간 발생

Error (onError) : 문서나 이미지를 읽는 중에 강제로 중지하는 순간 발생

Focus (onFocus) : 사용자가 입력 포커스를 원도우나 입력 양식의 요소로 이동했을 때

KeyDown (onKeyDown) : 사용자가 키를 눌렀을때

KeyPress (onKeyPress) : 사용자가 키를 누르고 있을때

KeyUp( onKeyUp) : 사용자가 눌렀던 키를 놓았을때

Load(onLoad) : 브라우저에서 문서을 읽었을때

MouseDown(onMouseDown) : 마우스를 누르는 순간 발생함

MouseMove(onMouseMove) : 마우스가 움직일 때

MouseOver(onMouseOver) : 사용자가 link anchor위로 마우스로 옮겼을때

MouseOut(onMouseOut) : 마우스가 특정 영역 안에 있다가 나갔을때

MouseUp(onMouseUp) : 마우스 커서를 이미지 맵이나 링크 위에서 내려 놓을 때

Move(onMove) : 윈도우나 프레임의 위치가 이동되는 순간 발생

Reset (onReset) : 사용자가 입력 양식을 초기화 했을 때

 

이벤트에서 발생하는 객체들의 종류이며 , 네스케이프와 익스플로어의 경우를 따로 분리했다.

[네스케이프  에서의 이벤트 객체]

data : DragDrop 이벤트로 인해 드롭된 객체의 URL이 들어있는 스트링 배열

height, width : 윈도우나 프레인의 길이와 너비(픽셀표시)

pageX, pageY : 픽셀로 나타낸 커서의 수평/수직 위치(페이지에서의 상대적위치)

screenX, screenY : 픽셀로 나타낸 커서의 수평/수직 위치(화면에서의 상대적 위치)

layerX, layerY : 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 레이어에 대한 상대적 위치.

target : 이벤트가 전송된 원래 객체

type : 발생한 이벤트 유형

which : 눌려진 마우스 버튼(left:1, middle:2, right:3)이나 눌려진 키의 ASCII

modifiers : 마우스나 키 이벤트와 연관된 수정자 키

(ALT_MASK,CONTROL_MASK,SHIFT_MASK,META_MASK) 를 식별

 

[익스플로어 에서의 이벤트 객체]

screenX, screenY : 픽셀로 나타낸 커서의 수평/수직 위치(화면에서의 상대적 위치)

clientX, clientY : 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 웹페이지에서의 상대적 위치

offsetX, offsetY : 픽셀로 나타낸 커서의 수평/수직 위치,이벤트가 발생한 컨테이너에 대한 상대적 위치

X, Y : 픽셀로 나타낸 커서의 수평/수직 위치, 이벤트가 발생한 문서에 대한 상대적 위치

srcElement : 이벤트가 전송된 원래 객체

type : 발생한 이벤트 유형

keyCode : 키 누름과 연관된 Unicode 키 코드를 식별

button : 이벤트가 발생했을 때 눌려진 마우스 버튼 식별(0:눌려진버튼없음, 1:, 2:, 4:)

altkey,ctrlkey,shiftkey : true false로 설정하여 이벤트가 발생했을 때 Alt키와 Control, Shift 키 중에 어떤 것이 눌려졌는지 알려준다.

cancelBubble : true false로 설정하여 이벤트 버블링을 취소하거나 활성화한다.

fromElement, toElement : 이동 중인 HTML 요소 지정

reason : 데이터 소스 객체에 대한 데이터 전송 상태를 나타내는데 사용

returnValue : true false로 설정하여 이벤트 핸들러의 리턴값을 나타낸다. 이벤트 핸들러에서 true false를 리턴하는 것과 같다.

 

위에서 열거한 이런 내용을 암기는 하지 못하더라도 모두 이해하고 어떤경우에 쓰이는지를

파악하고 있어야하겠다. 자바스크립트를 사용하는 사람들의 가장 기본적으로 갖추어야 하는 지식이다.



출처 : http://mainia.tistory.com/entry/Javascript-에서-알아야할-기초사항

Posted by 1010
반응형
프로젝트에 나가 주로 쓰이는 자바스크립트 함수를 모아 놓은것이다. 필요하다 싶으면 이 페이지에
업데이트하여 필요할때 복사해 쓸 작정이다.

 

/**

 * 입력값이  null 인지 체크한다

 */

function isNull(input){

       if (input.value == null || input.value == ""){

             return true;

       }else{

             return false;

       }

}

/**

 * 입력값이 스페이스 이외의 의미있는 값이 있는지 체크한다

 * if (isEmpty(form.keyword)){

 *       alert('값을 입력하여주세요');

 * }

 */

function isEmpty(input){

       if (input.value == null || input.value.replace(/ /gi,"") == ""){

             return true;

       }else{

             return false;

       }

}

/**

 * 입력값에 특정 문자가 있는지 체크하는 로직이며

 * 특정문자를 허용하고 싶지 않을때 사용할수도 있다

 * if (containsChars(form.name, "!,*&^%$#@~;")){

 *       alert("특수문자를 사용할수 없습니다");

 * }

 */

function containsChars(input, chars){

       for (var i=0; i < input.value.length; i++){

             if (chars.indexOf(input.value.charAt(i)) != -1){

                    return true;

             }

       }

       return false;

}

/**

 * 입력값이 특정 문자만으로 되어있는지 체크하며

 * 특정문자만을 허용하려 할때 사용한다.

 * if (containsChars(form.name, "ABO")){

 *    alert("혈액형 필드에는 A,B,O 문자만 사용할수 있습니다.");

 * }

 */

function containsCharsOnly(input, chars){

       for (var i=0; i < input.value.length; i++){

             if (chars.indexOf(input.value.charAt(i)) == -1){

                    return false;

             }

       }

       return true;

}

/**

 * 입력값이 알파벳인지 체크

 * 아래 isAlphabet() 부터 isNumComma()까지의 메소드가 자주 쓰이는 경우에는

 * var chars 변수를 global 변수로 선언하고 사용하도록 한다.

 * var uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

 * var lowercase = "abcdefghijklmnopqrstuvwxyz";

 * var number = "0123456789";

 * function isAlphaNum(input){

 *       var chars = uppercase + lowercase + number;

 *    return containsCharsOnly(input, chars);

 * }

 */

function isAlphabet(input){

       var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

       return containsCharsOnly(input, chars);

}

/**

 * 입력값이 알파벳 대문자인지 체크한다

 */

 function isUpperCase(input){

       var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

       return containsCharsOnly(input, chars);

 }

/**

 * 입력값이 알파벳 소문자인지 체크한다

 */

function isLowerCase(input){

       var chars = "abcdefghijklmnopqrstuvwxyz";

       return containsCharsOnly(input, chars);

}

/**

 * 입력값이 숫자만 있는지 체크한다.

 */

function isNumer(input){

       var chars = "0123456789";

       return containsCharsOnly(input, chars);

}

/**

 * 입려값이 알파벳, 숫자로 되어있는지 체크한다

 */

function isAlphaNum(input){

       var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

       return containsCharsOnly(input, chars);

}

/**

 * 입력값이 숫자, 대시"-" 되어있는지 체크한다

 * 전화번호나 우편번호, 계좌번호에 -  체크할때 유용하다

 */

function isNumDash(input){

       var chars = "-0123456789";

       return containsCharsOnly(input, chars);

}

/**

 * 입력값이 숫자, 콤마',' 되어있는지 체크한다

 */

function isNumComma(input){

       var chars = ",0123456789";

       return containsCharsOnly(input, chars);

}

/**

 * 입력값이 사용자가 정의한 포맷 형식인지 체크

 * 자세한 format 형식은 자바스크립트의 'reqular expression' 참고한다

 */

function isValidFormat(input, format){

       if (input.value.search(format) != -1){

             return true; // 올바른 포멧형식

       }     

       return false;

}

/**

 * 입력값이 이메일 형식인지 체크한다

 * if (!isValidEmail(form.email)){

 *       alert("올바른 이메일 주소가 아닙니다");

 * }

 */

function isValidEmail(input){

       var format = /^((\w|[\-\.])+)@((\w|[\-\.])+)\.([A-Za-z]+)$/;

       return isValidFormat(input, format);

}

/**

 * 입력값이 전화번호 형식(숫자-숫자-숫자)인지 체크한다

 */

function isValidPhone(input){

       var format = /^(\d+)-(\d+)-(\d+)$/;

       return isValidFormat(input, format);

}

/**

 * 입력값의 바이트 길이를 리턴한다.

 * if (getByteLength(form.title) > 100){

 *    alert("제목은 한글 50 (영문 100) 이상 입력할수 없습니다");

 * }

 */

function getByteLength(input){

       var byteLength = 0;

       for (var inx = 0; inx < input.value.charAt(inx); inx++)     {

             var oneChar = escape(input.value.charAt(inx));

             if (oneChar.length == 1){

                    byteLength++;

             }else if (oneChar.indexOf("%u") != -1){

                    byteLength += 2;

             }else if (oneChar.indexOf("%") != -1){

                    byteLength += oneChar.length / 3;

             }

       }

       return byteLength;

}

/**

 * 입력값에서 콤마를 없앤다

 */

function removeComma(input){

       return input.value.replace(/,/gi,"");

}

/**

 * 선택된 라디오버튼이 있는지 체크한다

 */

function hasCheckedRadio(input){

       if (input.length > 1){

             for (var inx = 0; inx < input.length; inx++){

                    if (input[inx].checked) return true;

             }

       }else{

             if (input.checked) return true;

       }

       return false;

}

/**

 * 선택된 체크박스가 있는지 체크

 */

function hasCheckedBox(input){

       return hasCheckedRadio(input);

}



Posted by 1010
반응형

웹 문서에서 아이디나 비밀번호 또는 다른 데이터 들을 서버측 으로 보낸 다음 수행이 되는 경우가 있다. 이때 문서에서 서버측 으로 데이터가 전달되는 방법이 2가지가 있는데 GET 방식과 POST방식이다. 각각의 방식들은 나름대로의 장단점을 가지고 데이터를 전달하는 역할을 한다.


GET 방식

1.웹 브라우저의 주소 입력란에서 아래와 같이 직접 입력하여도 데이터를 서버로 전송한다.(클라이언트로 부터의 데이터를 이름과 값이 겨합된 스트링 형태로 전달 하므로 각각 이름과 값은 “&”를 이용하여 결합한다.

ex) (http://localhost/chs/book/Request.jsp?Name=Michael&Depy=Computer)

2.기본적으로 데이터베이스에 대한 질의어 데이터와 같은 요청을 위한 정보를 전송할 때 사용

3.GET방식으로 보낼때는 같이 딸려가는 글자수에 제한이 있다(255자).

4.GET 방식을 사용하면 이를 초과하는 데이터가 절단된다.

5.GET 방식을 사용하면 데이터가 주소 입력란에 표시되므로 최소한의 보안도 유지되지 않는다.

6.GET 방식은 정보를 URL의 끝에 질의 문자열로서 서버로

Posted by 1010