개발일정에 치여 도무지 블로깅 할 시간이 안나 미치겠네요. 새로운 것 정리하기는 힘들고 자주 사용하고 있는 Ajax 패턴 정리해 봅니다.
Ajax 구현할 때는 거의 jQuery 를 활용하고 있습니다. 모바일 웹 구현할 때 네이티브 앱과 같은 UX 를 위해 Ajax 를 많이 사용하게 됩니다.
  • 로그인
로그인은 보통 화면에서 폼 값을 입력한 후 해당 값과 함께 ajax 호출합니다.
호출된 액션에서 로그인 관련 인증 및 예외처리 프로세스를 돌인 후
인증 상태에 따라 결과 값을 출력합니다.
출력된 값에 따라 로그인 페이지에서 경고를 띄우든 다음 페이지로 진행하든 처리하죠.
ajax 루틴을 돌고 있을 때 사용할 로딩 바를 띄우는 작업도 함께 해주면 좀더 나은 UX 를 구현할 수 있겠죠.
- login view script
<script>
function checkLogin(){
    
    if( $.trim($("#userId").val()) == '' ){
        alert("아이디를 입력해 주세요.");
        $("#userId").focus();
        return;
    }
    if( $.trim($("#userPw").val()) == '' ){
        alert("비밀번호를 입력해 주세요.");
        $("#userPw").focus();
        return;
    }
    // 로그인 프로세스 호출
    $.ajax({
        type: 'post'
        , async: true
        , url: '/member.do?cmd=login'
        , data: $("#frm").serialize()
        , beforeSend: function() {
             $('#ajax_load_indicator').show().fadeIn('fast');
          }
        , success: function(data) {
            var response = data.trim();
            console.log("success forward : "+response);
            // 메세지 할당
            switch(response) {
                case "nomatch":
                    msg = "아이디 또는 비밀번호가 일치하지 않습니다."; break;
                case "fail":
                    msg = "로그인에 실패 했습니다."; break;
                default :
                    msg = "존재하지 않는 사용자입니다."; break;
            }
            // 분기 처리
            if(response=="success"){
                window.location.href = "${targetUrl}";
            } else {
                alert(msg);
            }
          }
        , error: function(data, status, err) {
         console.log("error forward : "+data);
            alert('서버와의 통신이 실패했습니다.');
          }
        , complete: function() {
         $('#ajax_load_indicator').fadeOut();
          }
    });
}
</script>
- login view html
<form id="frm" name="frm" method="post" action="" onSubmit="checkLogin();return false;">
    <fieldset>
        <legend>login</legend>
        <div class="login_item mg_top34">
            <label>id</label>
            <input id="userId" name="memberVo.xcWebMbrId" type="text" class="i_login" />
        </div>
        <div class="login_item mg_top10">
            <label>password</label>
            <input id="userPw" name="memberVo.xcPswd" type="password" class="i_login" />
        </div>
        
        <div id="ajax_load_indicator" style="display:none">
            <p style="text-align:center; padding:16px 0 0 0"><img src="/mobile/common/img/ajax-loader-line.gif" /></p>
        </div>
        <p class="keeping mg_left89">
            <input id="keepidpw" class="rd_box22" value="1" type="checkbox" name="idPswdSave" >
            <label for="keepidpw">ID/PW 저장</label>
        </p>
        <p class="keeping mg_left20">
            <input id="keepid" class="rd_box22" value="1" type="checkbox" name="idSave" >
            <label for="keepid">ID 저장</label>
        </p>
        <span class="btn_login">
            <input type="image" src="<%=imageUrl%>/btn/btn_login.jpg" title="로그인" onclick="checkLogin();return false;">
        </span>
        <p class="btn_register"><a href="/member.do?cmd=memberJoin"><img src="<%=imageUrl%>/btn/btn_join.jpg" alt="회원가입" /></a>
        <a href="/member.do?cmd=goIdPwFind" class="mg_left5"><img src="<%=imageUrl%>/btn/btn_sch.jpg" alt="아이디/비밀번호 찾기" /></a></p>
    </fieldset>
</form>
- login ajax result
<%@ include file="/mobile/common/include/config.jsp" %>
${result}
  • 내용 추가
페이지 하단으로 스크롤 이동했을 때 추가되는 자동으로 다음 페이지 데이터가 추가되는 UX를 구현할 때 사용하는 기법으로 jQuery 의 append() 함수를 사용할 수 있다.
- product list view script
<script>
function paging(){
    count++;
    
    $.ajax({
        type: 'post'
        , async: true
        , url: "/display.do?cmd=productListAppend&ordFlag="+'${ordFlag}'+"&categoryCd="+categoryCd+"&itemCode="+'${itemCode}'+"&count="+count
        , beforeSend: function() {
             $('#ajax_load_indicator').show().fadeIn('fast');
          }
        , success: function(data) {
            var response = data.trim();
            console.log("success forward : "+response);
            // 상품 리스트 할당
            $('#view_list').append(response);
            $('#product_count').html($('#view_list li.thumb').size());
          }
        , error: function(data, status, err) {
            console.log("error forward : "+data);
            alert('서버와의 통신이 실패했습니다.');
          }
        , complete: function() {
            $('#ajax_load_indicator').fadeOut();
          }
    });
}
</script>
- product list view html
<!-- 상품 목록 -->
<div id="view_list" class="product_list" style="display: none;">
<c:forEach var="list" items="${returnMap}">
  <a href="/display.do?cmd=productView&brandCd=${list.brandCd }&prodCd=${list.prodCd }&ordFlag=${ordFlag }&styleYY=${list.styleYY }&priceDpYn=${list.priceDpYn }&listPrice=${list.listPrice }&categoryCd=${categoryCd}&itemCode=${itemCode}&rNum=${list.rNum }&count=${count}">
    <ul>
      <li class="thumb"><img src="${list.listImg }" alt="상품이미지" /></li>
      <li class="b_title"><span class="brand">[${list.brandNm }]</span><span class="title">${list.prodNm }</span></li>
      <li class="price">
      <c:if test="${list.priceDpYn eq 'Y'}">
      ${list.listPrice }원
      </c:if>
      <c:if test="${list.priceDpYn eq 'N'}">
      <span><a href="#"><img src="<%=imageUrl%>/common/ic_login.png" alt="로그인" /></a></span>
      </c:if>
      </li>
      <li class="btn_go"><img src="<%=imageUrl%>/btn/btn_go.png" alt="" /></li>
    </ul>
  </a>
</c:forEach>
</div>
<div id="ajax_load_indicator" style="display:none">
    <p style="text-align:center; padding:14px 0 14px 0"><img src="/mobile/common/img/ajax-loader-line.gif" /></p>
</div>
    
<!-- 더보기 bar-->
<div class="more_bar">
<a href="javascript:paging()">
  <ul class="sec01">
    <li class="btn_arr"><img src="<%=imageUrl%>/common/arr_down.png" alt="" /></li>
    <li class="text_more">15개 더보기</li>
    <li class="text_num"><span id="product_count">${total}</span> / 999</li>
  </ul>
  </a>
  <p><a href="#"><img src="<%=imageUrl%>/btn/btn_top.jpg" alt="맨위로" /></a></p>
</div>  
- append view html
<%@ include file="/mobile/common/include/config.jsp"%>
<!-- 상품 목록 -->
<c:forEach var="list" items="${returnMap}">
    <a href="/display.do?cmd=productView&brandCd=${list.brandCd }&prodCd=${list.prodCd }&ordFlag=${ordFlag }&styleYY=${list.styleYY }&priceDpYn=${list.priceDpYn }&listPrice=${list.listPrice }&categoryCd=${categoryCd}&itemCode=${itemCode}&rNum=${list.rNum }&count=${count}">
        <ul>
            <li class="thumb"><img src="${list.listImg }" alt="상품이미지" /></li>
            <li class="b_title"><span class="brand">[HAZZYS]</span><span
                class="title">${list.prodNm }</span></li>
            <li class="price">
            <c:if test="${list.priceDpYn eq 'Y'}">
            ${list.listPrice }원
            </c:if>
            <c:if test="${list.priceDpYn eq 'N'}">
            <span><a href="#"><img src="<%=imageUrl%>/common/ic_login.png" alt="로그인" /></a></span>
            </c:if>
            </li>
            <li class="btn_go"><img src="<%=imageUrl%>/btn/btn_go.png" alt="" /></li>
        </ul>
    </a>
</c:forEach>
 

If anything about current interaction design can be called “glamorous,” it’s creating Web applications. After all, when was the last time you heard someone rave about the interaction design of a product that wasn’t on the Web? (Okay, besides the iPod.) All the cool, innovative new projects are online.

Despite this, Web interaction designers can’t help but feel a little envious of our colleagues who create desktop software. Desktop applications have a richness and responsiveness that has seemed out of reach on the Web. The same simplicity that enabled the Web’s rapid proliferation also creates a gap between the experiences we can provide and the experiences users can get from a desktop application.

That gap is closing. Take a look at Google Suggest. Watch the way the suggested terms update as you type, almost instantly. Now look at Google Maps. Zoom in. Use your cursor to grab the map and scroll around a bit. Again, everything happens almost instantly, with no waiting for pages to reload.

Google Suggest and Google Maps are two examples of a new approach to web applications that we at Adaptive Path have been calling Ajax. The name is shorthand for Asynchronous JavaScript + XML, and it represents a fundamental shift in what’s possible on the Web.

Defining Ajax

Ajax isn’t a technology. It’s really several technologies, each flourishing in its own right, coming together in powerful new ways. Ajax incorporates:

The classic web application model works like this: Most user actions in the interface trigger an HTTP request back to a web server. The server does some processing—retrieving data, crunching numbers, talking to various legacy systems—and then returns an HTML page to the client. It’s a model adapted from the Web’s original use as a hypertext medium, but as fans of The Elements of User Experience know, what makes the Web good for hypertext doesn’t necessarily make it good for software applications.

사용자 삽입 이미지

Figure 1: The traditional model for web applications (left) compared to the Ajax model (right).

This approach makes a lot of technical sense, but it doesn’t make for a great user experience. While the server is doing its thing, what’s the user doing? That’s right, waiting. And at every step in a task, the user waits some more.

Obviously, if we were designing the Web from scratch for applications, we wouldn’t make users wait around. Once an interface is loaded, why should the user interaction come to a halt every time the application needs something from the server? In fact, why should the user see the application go to the server at all?

How Ajax is Different

An Ajax application eliminates the start-stop-start-stop nature of interaction on the Web by introducing an intermediary—an Ajax engine—between the user and the server. It seems like adding a layer to the application would make it less responsive, but the opposite is true.

Instead of loading a webpage, at the start of the session, the browser loads an Ajax engine—written in JavaScript and usually tucked away in a hidden frame. This engine is responsible for both rendering the interface the user sees and communicating with the server on the user’s behalf. The Ajax engine allows the user’s interaction with the application to happen asynchronously—independent of communication with the server. So the user is never staring at a blank browser window and an hourglass icon, waiting around for the server to do something.

사용자 삽입 이미지

Figure 2: The synchronous interaction pattern of a traditional web application (top) compared with the asynchronous pattern of an Ajax application (bottom).

Every user action that normally would generate an HTTP request takes the form of a JavaScript call to the Ajax engine instead. Any response to a user action that doesn’t require a trip back to the server—such as simple data validation, editing data in memory, and even some navigation—the engine handles on its own. If the engine needs something from the server in order to respond—if it’s submitting data for processing, loading additional interface code, or retrieving new data—the engine makes those requests asynchronously, usually using XML, without stalling a user’s interaction with the application.

Who’s Using Ajax

Google is making a huge investment in developing the Ajax approach. All of the major products Google has introduced over the last year—Orkut, Gmail, the latest beta version of Google Groups, Google Suggest, and Google Maps—are Ajax applications. (For more on the technical nuts and bolts of these Ajax implementations, check out these excellent analyses of Gmail, Google Suggest, and Google Maps.) Others are following suit: many of the features that people love in Flickr depend on Ajax, and Amazon’s A9.com search engine applies similar techniques.

These projects demonstrate that Ajax is not only technically sound, but also practical for real-world applications. This isn’t another technology that only works in a laboratory. And Ajax applications can be any size, from the very simple, single-function Google Suggest to the very complex and sophisticated Google Maps.

At Adaptive Path, we’ve been doing our own work with Ajax over the last several months, and we’re realizing we’ve only scratched the surface of the rich interaction and responsiveness that Ajax applications can provide. Ajax is an important development for Web applications, and its importance is only going to grow. And because there are so many developers out there who already know how to use these technologies, we expect to see many more organizations following Google’s lead in reaping the competitive advantage Ajax provides.

Moving Forward

The biggest challenges in creating Ajax applications are not technical. The core Ajax technologies are mature, stable, and well understood. Instead, the challenges are for the designers of these applications: to forget what we think we know about the limitations of the Web, and begin to imagine a wider, richer range of possibilities.

It’s going to be fun.


Caps Lock키 일명 대문자키(?)가 켜저있는지 확인하는 자바 스크립트이다.

뭐 별나게 쓸 일을 없지만, 소문자만 영어만 사용하는 곳에서는 꼭 필요한듯한 자바스크립트이다.
 

function checkCapsLock( e ) {
 var myKeyCode=0;
 var myShiftKey=false;
 var myMsg='Caps Lock이 켜져있습니다. 확인하세요!';

 // Internet Explorer 4+
 if ( document.all ) {
  myKeyCode=e.keyCode;
  myShiftKey=e.shiftKey;

 // Netscape 4
 } else if ( document.layers ) {
  myKeyCode=e.which;
  myShiftKey=( myKeyCode == 16 ) ? true : false;

 // Netscape 6
 } else if ( document.getElementById ) {
  myKeyCode=e.which;
  myShiftKey=( myKeyCode == 16 ) ? true : false;

 }

 // Upper case letters are seen without depressing the Shift key, therefore Caps Lock is on
 if ( ( myKeyCode >= 65 && myKeyCode <= 90 ) && !myShiftKey ) {
  alert( myMsg );

 // Lower case letters are seen while depressing the Shift key, therefore Caps Lock is on
 } else if ( ( myKeyCode >= 97 && myKeyCode <= 122 ) && myShiftKey ) {
  alert( myMsg );

 }
}

가끔 자바스크립트에서 딜레이가 필요한 경우가 있다.

보통

setTimeout("hideMessage()", 1000);


이렇게 많이 사용한다.
하지만...

이건 함수를 딜레이 시켜 실행 하는 부분이고,
가끔 정상적으로 동작을 하지 않는 경우를 확인했다..ㅠ,.ㅍ

왜!! 저 setTimeout() 함수가 정상 적동을 하지 않는지 아직도 의문 이다...ㅡㅡ;;
그래서 결국 자바스크립트에서 딜레이 함수를 별도로 만들었다.

function delay(gap){ /* gap is in millisecs */
  var then,now;
  then=new Date().getTime();
  now=then;
  while((now-then)<gap){
    now=new Date().getTime();
  }
}

작동 잘~ 된다!! ㅋㅋ

이메일 체크 정규식
/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i;


핸드폰번호 정규식
/^\d{3}-\d{3,4}-\d{4}$/;


일반 전화번호 정규식
/^\d{2,3}-\d{3,4}-\d{4}$/;


아이디나 비밀번호 정규식
 /^[a-z0-9_]{4,20}$/;


var regExp = /^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/;


if ( !regExp.test( document.frm.hp.value ) ) {
      alert("잘못된 휴대폰 번호입니다. 숫자, - 를 포함한 숫자만 입력하세요.");
      return false
}

Script.aculo.Us에서는 드래그앤드롭(Drag N Drop)을 쉽게 구현할 수 있는 클래스가 있는데 Draggable(Droppables)과 Sortable 2개의 클래스이다. 둘다 드래그앤드롭을 위한 클래스인데 Draggable는 객체를 드래그 가능하게 만드는 클래스이고 Sortable은 드래그앤드롭이 되면서 정렬이 가능하도록 하는 클래스이다. 정렬을 하고자 한다면 Sortable을 사용하는 것이 편하고 여기서 정리하려는 것은 Sortable이다.

Sortable.create('id_of_container',[options]);

위 코드이 Sortable 을 사용하는 기본 문법이다. id_of_container에 드래그앤드롭을 가능하게 할 엘리먼트의 id를 주고 options에 드래그앤드롭에 대한 옵션을 JSON형태로 던져주면 바로 정렬가능한 드래그앤드롭을 사용가능하다.  id_of_container이라고 쓴 것처럼 드래그할 객체가 아니라 드래그할 객체들을 담고 있는 container의 id를 주면 되고 options는 안주면 디폴트옵션으로 동작하게 된다.

예를 들어

  1. <ul id="contailner"> 
  2.     <li id="dnd_1">Test 1</li> 
  3.     <li id="dnd_2">Test 2</li> 
  4. <ul> 
  5. <script type="text/javascript"> 
  6.     Sortable.create("contailner");  
  7. </script> 

위와같이 작성하면 dnd_1, dnd_2객체가 바로 드래그앤드롭이 가능하다. (이 얼마나 간단하단 말인가. ㅎㅎㅎ)

이제 옵션을 보자. 자유롭게 사용하려면 옵션을 주어서 원하는 형태로 사용하여야 한다. 옵션은 Draggable과 공통적인 것도 있고 아닌것들도 있다.(아직 Script.aculo.us의 API리스트는 솔직히 좀 아쉽다.) API와 내가 테스트해본걸 바탕으로 적었지만 빠진 부분이 있을수도 있다.

tag : 여기에 HTML태그명을 주면 해당 태그에 대해서 Sortable이 동작하게 된다. 디폴트는 li태그이고 container아래 한단계 밑까지만 동작한다. 쉽게 말해 li안에 li가 또 들어있다고 하더라도 안에 있는 li에는 드래그앤드롭이 동작하지 않는다. Block엘리먼트에만 가능하고 table같은걸 블가능하다.

only : 이 옵션을 주고 여기서 class명을 지정하면 tag에 설정한 태그명이라고 할지라도 only에서 준 class명과 맞지 않으면 드래그앤드롭이 동작하지 않는다.

overlap : 가로 리스트는 horizontal, 세로 리스트는 vertical로 설정하라는데 정확한 동작은 잘 모르겠다.

constraint : horizontal, vertical, false 3가지가 있고 드래그앤드롭의 방향을 설정한다. horizontal/vertical로 설정할 경우에는 가로/세로로만 이동하며 false나 옵션을 주지 않았을 경우에는 어떤 방향이든지 이동이 가능하다.

containment : 이곳에 container 리스트를 지정하고 이곳에 지정한 container간에는 드래그앤드롭이 가능하다.

handle : 드래그앤드롭을 할 엘리먼트에서 전체가 아닌 특정부분만을 이용해서 드래그앤드롭이 가능하도록 하고 싶을때 handle이용한다. 이곳에 id 혹은 class명을 지정하면 핸들러로 사용할 수 있다.

delay : 드래그앤드롭으로 반응할 시간을 미리세컨단위로 설정할 수 있고 기본은 0이다. 너무 민감하게 반응하지 않기를 바랄때는 delay의 숫자를 크게 지정할 수 있다.

dropOnEmpty : true로 설정하면 container가 비어있을때도 drop이 가능하다. false일 경우에는 container에 다른 드래그앤드롭객체가 있을때만 드롭이 가능하다. 기본은 false

scroll : 기본으로는 지정되어 있지 않으며 window로 설정할 경우에는 드롭할 container가 화면밖에 있을경우에 드래그객체가 화면밖으로 나가면 자동으로 스크롤한다.

scrollSensitivity : 기본은 20이고 스크롤이 되게 하기 위해서 넘어가야하는 크기를 지정한다.

scrollSpeed : 스크롤 속도이고 픽셀로 지정하면 기본은 15이다.

onChange : 콜백함수로 드래그앤드롭을 시작하는 등 객체의 위치가 변경되면 계속 발생한다.

onUpdate : 콜백함수로 드래그앤드롭을 하여 실제 순서의 변화가 생겼을때만 발생한다.

 





아주 간단한 예제를 만들었다. 동작과 소스코드를 보면 쉽게 이해할 수 있을꺼라고 생각한다. 최근 작업을 하면서 몇가지 주의점(?)을 발견한 거라면...

  • container의 id에 언더바(_)가 들어가면 동작하지 않는다.
  • Sortable.serialize를 사용하려면 드래그앤드롭 엘리먼트의 아이디가 언더바(_)로 이어져야 한다. 언더바 뒤쪽에 있는 문자만 표시된다.
  • IE에서는 왼쪽 콘테이너에서 오른쪽 콘테이너로 갈때 드래그엘리먼트가 컨테이너 뒤쪽으로 가는 문제가 생긴다. 드롭하기 위해서 반이상 넘어갈 경우에는 위로 올라오는데 이건 IE의 z-index버그때문에 생기는 문제로 예상되는데 정확한 해결책은 아직 찾지 못했다.
Sortable.serialize는 해당 컨테이너에 있는 드래그앤드롭객체를 순서대로 보여준다. 이것은 위치정렬을 한 후에 Ajax등을 통해서 새로 정렬한 위치를 서버에 저장할 수 있도록 하는 역할을 한다.

그리고 예제의 소스를 보면 알겠지만 기본적으로는 드래그앤드롭을 할 때 해당위치의 공간은 표시하지만 따로 표시되지는 않는다. 이 문제를 해결하기 위해 더미 엘리먼트를 만들었다. OnChage가 발생할 때 해당 엘리먼트의 바로 앞쪽에 더미엘리먼트를 만들어서 insert한다. 이렇게 함으로써 드롭했을때 떨어질 위치가 명시적으로 보일수 있도록 하고 OnChange는 계속 발생하기 때문에 처음에 더미엘리먼트를 지우고 다시 넣어주기 때문에 다른 컨테이너로 넘어가는 순간 더미엘리먼트도 적절하게 이동된다. 깔끔한 해결책은 아닌듯 하지만 일단 동작은 한다.
항상 뭘하다보면 자기 중심적으로 생각하게 되는것 같습니다. 상대방의 입장에서 생각해야 되는데 그게 쉽지 않습니다. 더군다나 웹에서는 상대방(?)의 대한 정보가 보통은 전무한 편이라서 더 자기중심적으로 생각하게 되는 경우가 많죠.

초창기에 개발에 대해 전혀 모를때 인터넷에 있는 많은 정보들을 볼 때 가장 답답한 부분중 하나가 설명하는 사람이 당연히 내가 알꺼라고 생각하고 그냥 넘어가는 부분을 정작 나는 몰라서 그사람의 설명이나 소스까지 도달하기도 어려웠다는 것이지요. 머 그렇다고 항상 모든 것을 다 설명한다는 것도 어렵겠지만 블로그에서는 최대한 자세하게 쓰려고 하고 있기는 하지만 좀 초심을 잃어버린 생각이 들었습니다. 그리고 새로 알게된걸 항상 포스팅으로 하게되지는 않고 그러다 보면 포스팅타이밍을 놓쳐버린 것들도 많죠.



쿡이님의 질문을 받으면서 생각난 김에 JS로 엘리먼트를 다룰때 가장 많이 사용할 추가, 삭제에서 prototype.js가 지원하는 부분에 대해서 다시 한번 정리합니다.

prototype.js에는 Element 클래스가 있습니다. HTML의 DIV, INPUT, LI같은 엘리먼트에 관련된 클래스입니다. Element의 API문서 를 보면Element클래스가 지원하는 많은 메서드를 볼 수 있습니다. 엘리먼트와 관련된 속성에 대한 것이라든지, 추가, 삭제, 생성등등의 기능을 지원하고 있습니다.




일반적인 방법
  1. <div id="testDivision" name="testDivision"> 
  2.     <a href="#">Link 1</a> 
  3. </div> 

간단한 HTML을 가지고 보겠습니다. 엘리먼트를 핸들링할때 JS에서 제공하는 2가지방법이 있습니다. innerHTML을 이용하는 방법과 DOM을 이용하는 방법입니다.

일반적으로는 innerHTML을 이용하는 것이 간단하면서도 편하기 때문에 많이 사용합니다.

  1. var htmlStr = "<a href='#'>Link 2</a>";  
  2. var obj = document.getElementById("testDivision");  
  3. obj.innerHTML = obj.innerHTML + htmlStr;  

사실 설명할 내용도 없긴 하지만 innerHTML은 이름 그대로 해당 엘리먼트의 안에 있는 HTML을 의미하고 있습니다. 내부 HTML을 새로지정하면 새로 지정하는 내용으로 replace가 됩니다. 기본의 innerHTML값과 새로추가할 HTML스트링을 문자열로 이어붙혀서 다시 innerHTML으로 할당해서 HTML의 구조를 동적으로 바꾸는 것입니다. js를 실행하면 HTML이 아래와 같은 모습이 됩니다.
  1. <div id="testDivision" name="testDivision"> 
  2.     <a href="#">Link 1</a> 
  3.     <a href="#">Link 2</a> 
  4. </div> 


두번째 방법은 DOM입니다. DOM은 Document Object Model의 약자로 표준이 정해져 있고 대부분의 브라우저가 지원하고 있습니다. 엘리먼트를 추가/삭제같은 DOM Level 2 에 정의가 되어 있습니다.(DOM Level 1에서 추가확장되어 현재는 대부분 Level 2를 지원하고 있는 것으로 알고 있습니다.) 이름대로 DOM을 다루기 위해서 만들어진 것이기 때문에 다양한 메서드를 제공하고 있고 좀 더 세련된 느낌의 사용법을 가지고 있습니다.

  1. var elem = document.createElement("a")  
  2. elem.setAttribute("href", "#");  
  3. elem.appendChild(document.createTextNode("Link 2"));  
  4. document.getElementById("testDivision").appendChild(elem);  

같은 기능을 DOM으로 구현한 것입니다. 엘리먼트 만들고 속성추가하고 TextNode만들어서 A엘리먼트 안에 넣은 다음에 추가한 것입니다. 메서드로 다양하게 다룰 수 있기는 하지만 저 간단한 소스도 소스로는 꽤 복잡하게 작성되고 있고 한눈에 어떻게 동작할 것인지를 파악하기가 쉽지 않고 복잡한 HTML의 경우에는 훨씬 복잡하게 됩니다. innerHTML에 비해서 특정엘리먼트만 지우는 remove관련 메서드도 지원하고 있기는 하지만 브라우져의 따라 DOM Level 1/2의 지원차이가 있습니다.

DOMDom Test Pages 에서 지원여부를 테스트해 볼 수 있고 PPK의 W3C DOM Compatibility 에서 브라우져별 차이를 파악할 수 있습니다.




prototype.js 이용하기
당연히 prototype.js를 로드해야하고 그 후에 다음과 같이 사용하면 됩니다.
  1. $("testDivision").insert("<a href='#'>Link 2</a>");  
  2. $("testDivision").update("<a href='#'>Link 2</a>");  
  3. $("testDivision").remove();  

너무 간단한 코드라서 그냥 한 코드블럭에 다 썼습니다. 첫줄 insert만으로 위에서 설명했던 기능과 동일한 기능을 합니다. update는 replace의 기능을 합니다. 2번째 줄을 실행하면 Div안에 link2만 존재하게 되겠고 remove를 실행하면 testDivision DIV자체가 삭제되어버립니다. 간단한 기능만 소개했지만 그외에도 Element관련 다양한 기능 을 제공하고 있습니다. prototype.js내부적으로 크로스 브라우징을 지원하기 때문에 브라우저호환에 대해서 큰 걱정없이 사용할 수 있습니다.

추가적으로 좀 더 세밀하게 컨트롤 할 수 있는 기능을 제공하고 있습니다.
  1. $("testDivision").insert({top:"<a href='#'>Link 2</a>"});  
  2. // 결과  
  3. // <div id="testDivision" name="testDivision">  
  4. //       <a href="#">Link 2</a><a href="#">Link 1</a>  
  5. // </div>  
  6.  
  7. $("testDivision").insert({bottom:"<a href='#'>Link 2</a>"});  
  8. // 결과  
  9. // <div id="testDivision" name="testDivision">  
  10. //       <a href="#">Link 1</a><a href="#">Link 2</a>  
  11. // </div>  
  12.  
  13.  
  14. $("testDivision").insert({bottom:"<a href='#'>Link 2</a>"});  
  15. // 결과  
  16. // <a href="#">Link 2</a>  
  17. // <div id="testDivision" name="testDivision">  
  18. //       <a href="#">Link 1</a>  
  19. // </div>  
  20.  
  21. $("testDivision").insert({after:"<a href='#'>Link 2</a>"});  
  22. // 결과  
  23. // <div id="testDivision" name="testDivision">  
  24. //       <a href="#">Link 1</a>  
  25. // </div>  
  26. // <a href="#">Link 2</a>  

위 코드처럼 JSON형태로 사용해서 insert되는 위치를 지정해 줄 수 있습니다. 사용할 수 있는 position값은 top, bottom, before, after입니다.  이걸 이용하면 쉽게 원하는 위치에 엘리먼트의 삽입/삭제가 가능합니다.

좀 복잡한 HTML의 경우에는 script.aculo.us의 Builder을 사용하는 것도 괜찮은 방법 같습니다.

<!--

// 최상위 체크 로직(chars로 넘긴 값이 있다면 true)

    function containsCharsOnly(input,chars) {

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

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

                return false;

        }

        return true;

    }

 

 

// 최상위 체크 로직(chars로 넘긴 값이 있다면 false)

 function containsChars(input,chars) {

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

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

            return true;

     }

     return false;

 }

 

 

 

// 숫자 체크

    function isNum(input) {

        var chars = "0123456789";

        return containsCharsOnly(input,chars);

    }

 

 

 

// 이름체크

 function nameCheck(input){

  var chars = '0123456789~!@#$%^&*()_-+=|{}[]<>,./?';

        return containsChars(input,chars);

 }

 

 

 

// 전화 번호 Check

    function isPhoneCheck(input) {

     var chars = "0123456789( ).-,<>{}[]_~";

        return containsCharsOnly(input,chars);

    }

 

 

 

// 영문 판별

    function isPhoneCheck(input) {

     var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

        return containsCharsOnly(input,chars);

    }

 

 

 

// 영숫자 판별

    function isPhoneCheck(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 형식은 자바스크립트의 ''regular expression''을 참조

 function isValidFormat(input,format) {

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

         return true; file://올바른 포맷 형식

     }

     return false;

 }

 

 

 

 /**

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

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

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

  *     }

  */

 function isValidEmail(input) {

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

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

     return isValidFormat(input,format);

 }

 

 

 

 /**

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

  */

 function isValidPhone(input) {

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

     return isValidFormat(input,format);

 }

 

 

 

 // 콤마 없애기

 function removeComma(input) {

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

 }

 

 

 

 // 문자 변환 함수

    function alterString(str,before,after) {

     var returnStr = "";

     for(i = 0; i < str.length; i++) {

      value = str.charAt(i);

      index = before.indexOf(value);

      if(index >= 0) value = after.charAt(index);

      returnStr += value;

     }

     return returnStr;

    }

 

 

 

// --> 대문자 변환 함수

    function ToUpper(arg) {

     var str1 = "abcdefghijklmnopqrstuvwxyz";

     var str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

     return alterString(arg,str1,str2);

    }

 

 

 

// --> 소문자 변환 함수

    function ToLower(arg){

     var str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

     var str2 = "abcdefghijklmnopqrstuvwxyz";

     return alterString(arg,str1,str2);

    }

 

 

 

// 반각 문자를 전각문자로

    function convert2ByteChar(x_char) {

        var x_2byteChar = ""; //컨버트된 문자

        var c = x_char.charCodeAt(0);

        if(32 <= c && c <= 126) { //전각으로 변환될수 있는 문자의 범위

            if(c == 32) { //스페이스인경우 ascii 코드 32

                x_2byteChar = unescape("%uFFFC");

            } else {

                x_2byteChar = unescape("%u"+gf_DecToHex(c+65248));

            }

        }

        return  x_2byteChar;

    }

 

 

 

// 10진수를 16진수로

    function gf_DecToHex(x_dec) {

        var x_Hex = new Array();

        var x_serial = 0;

        var x_over16 = x_dec;

        var x_tempNum = 0;

        while(x_dec > 15) {

            var x_h = x_dec % 16;          //나머지

            x_dec = parseInt(x_dec/16); //

            x_Hex[x_serial++] = (x_h > 9 ? String.fromCharCode(x_h + 55) : x_h); //16진수코드변환

        }

 

 

 

    //마지막은 몫의 값을 가짐

        x_Hex[x_serial++] = (x_dec > 9 ? String.fromCharCode(x_dec + 55) : x_dec); //16진수코드변환

  

    //,나머지,나머지,.....

        var retValue = "";

        for(var i=x_Hex.length ; i>0 ;i--) {

            retValue += x_Hex[i-1];

        }

        return retValue;

    }

 

 

 

// input box space, &nbsp;등 만으로 넣고 장난 칠때 이들 문자 뺀 길이를 통해 유효성 체크한다...

    function CheckStr(strOriginal, strFind, strChange){

        var position, strOri_Length;

        position = strOriginal.indexOf(strFind); 

        while (position != -1){

            strOriginal = strOriginal.replace(strFind, strChange);

            position = strOriginal.indexOf(strFind);

        }

        strOri_Length = strOriginal.length;

        return strOri_Length;

    }

 

 

 

// 체크 박스에 체크가 되어 있으면 true

 function checkValidator(str) {

  if(str.checked) return true;

  else return false;

 }

 

 

 

 // 비밀번호는 4자 등 최대 최소 길이를 파람으로 주고 처리...

    function checkLength(str,minLng,maxLng){

        var ckstr = str.value.length;

        if (parseInt(ckstr) < parseInt(minLng) || parseInt(ckstr) > parseInt(maxLng)) return false;

        return true;

    }

 

 

 

// 숫자만 받아서 아니면 메세지 보여 주는

    function onlyNumber(objEv) {

        if(!isNum(objEv)){

            alert("숫자만 입력가능합니다.");

            objEv.value = "";

            objEv.focus();

            return;

        }

    }

 

 

 

// 숫자를 체크하다가 6자 등 원하는 만큼 이동후 다음 input 박스로 이동 시키는...

    function goJump(fname, len, goname){

        onlyNumber(fname);

        if (document.all[fname].value.length == len) document.all[goname].focus();

    }

 

 

 

// 주민등록번호 체크 로직

    function check_ResidentNO(str_f_num,str_l_num){ 

        var i3=0

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

         var ch1 = str_f_num.substring(i,i+1);

            if (ch1<'0' || ch1>'9') i3=i3+1;

        }

        if ((str_f_num == '') || ( i3 != 0 )) return false;

        var i4=0;

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

            var ch1 = str_l_num.substring(i,i+1);

            if (ch1<'0' || ch1>'9') i4=i4+1;

        }

        if ((str_l_num == '') || ( i4 != 0 )) return false;

        if(str_f_num.substring(0,1) < 4) return false;

        if(str_l_num.substring(0,1) > 2) return false;

        if((str_f_num.length > 7) || (str_l_num.length > 8)) return false;

        if ((str_f_num == '72') || ( str_l_num == '18'))  return false;

               

        var f1=str_f_num.substring(0,1)

        var f2=str_f_num.substring(1,2)

        var f3=str_f_num.substring(2,3)

        var f4=str_f_num.substring(3,4)

        var f5=str_f_num.substring(4,5)

        var f6=str_f_num.substring(5,6)

        var hap=f1*2+f2*3+f3*4+f4*5+f5*6+f6*7

        var l1=str_l_num.substring(0,1)

        var l2=str_l_num.substring(1,2)

        var l3=str_l_num.substring(2,3)

        var l4=str_l_num.substring(3,4)

        var l5=str_l_num.substring(4,5)

        var l6=str_l_num.substring(5,6)

        var l7=str_l_num.substring(6,7)

        hap=hap+l1*8+l2*9+l3*2+l4*3+l5*4+l6*5

        hap=hap%11

        hap=11-hap

        hap=hap%10

        if (hap != l7) return false;

        return true;

    }

 

 

 

// 바이트 구하기

    function getByteLen(str){

        return(str.length+(escape(str)+"%u").match(/%u/g).length-1);

    }

 

 

 

 // url 가져오기

    function getUrlAddress(){

        var pageUrl = document.location;

     pageUrl  = new String(pageUrl);

      return pageUrl.substring(0,pageUrl.lastIndexOf("/"));

    }

 

 

 

// 오른마우스 금지, 나중에 해당 주석 풀고 사용

    function rightbutton(e){

        if (navigator.appName == 'Netscape' &&  (e.which == 3 || e.which == 2))

            return false;

        else if (navigator.appName == 'Microsoft Internet Explorer' && (event.button == 2 || event.button == 3))

        {

            alert("죄송합니다!! 정보무단복제를 막기 위하여 오른쪽 마우스 사용을 허용하지 않습니다.");

            return false;

        }

        return true;

    }

 

 

 

//document.onmousedown=rightbutton;

 

// 컨트롤 키 금지, 나중에 해당 주석 풀고 사용

    function checkCtl(){

        if (document.all){

            if(event.keyCode==17) {

                alert("죄송합니다!! 컨트롤키 사용을 허용하지 않습니다.");

                return false;

            }

        }

    }

 

 

 

//document.onkeydown = checkCtl;

 

 function setCookie(name,value) {

     document.cookie = name+"="+escape(value)+";path=/;domain=.kkaok.pe.kr;";

 }

 

 function setCookie(name,value, expires) {

     document.cookie = name + "=" + escape(value) +

     "; path=/; expires=" + expires.toGMTString();

 }

 

 function getCookie(Name) {

     var search = Name + "="

     if (document.cookie.length > 0) { // 쿠키가 설정되어 있다면

         offset = document.cookie.indexOf(search)

         if (offset != -1) { // 쿠키가 존재하면

             offset += search.length

         // set index of beginning of value

             end = document.cookie.indexOf(";", offset)

         // 쿠키 값의 마지막 위치 인덱스 번호 설정

             if (end == -1)

                 end = document.cookie.length

             return unescape(document.cookie.substring(offset, end));

         }

     }

 }

 

 

 

    String.prototype.trim = function(){

        return this.replace(/(^\s*)|(\s*$)/gi, "");

    }

 

//문자 바꾸기, 사용법 var str = 문자열.replaceAll("a", "1"); 

    String.prototype.replaceAll = function(str1, str2) {

        var temp_str = "";

        if (this.trim() != "" && str1 != str2) {

            temp_str = this.trim();

            while (temp_str.indexOf(str1) > -1){

                temp_str = temp_str.replace(str1, str2);

            }

        }

        return temp_str;

    }

 

//-->

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
 <HEAD>
  <TITLE> New Document </TITLE>
  <META NAME="Generator" CONTENT="EditPlus">
  <META NAME="Author" CONTENT="">
  <META NAME="Keywords" CONTENT="">
  <META NAME="Description" CONTENT="">

  <script language="JavaScript">
function test()
{
 var date = new Date();
 date.setFullYear('2008','11','16' -16);

 alert(date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate());
}
  </script>
 </HEAD>

 <BODY>
  <a href="javascript:test();">test</a>
 </BODY>
</HTML>

function getCon(){

 var len=0, j;
 var str = document.board.content.value;

 for (i=0, j=str.length;i<j;i++, len++) {

  if ( (str.charCodeAt(i)<0)||(str.charCodeAt(i)>127) ){
   len = len+1;
  }

  if (len >= 20000) {
   alert(''최대 2000 Bytes 까지만 보낼 수 있습니다.'');
   document.board.content.value=str.substring(0,i);
   document.board.content.focus();
   return;
  }

 }
}

<textarea name="content" cols="70" rows="15" onclick="getCon()" onkeyup="getCon()"></textarea>

사용자 삽입 이미지

open flash chart를 data file 없이 사용 하는 방법입니다.
서버 단에서 밑에 javascript 부분을 text로 생성한 다음 화면에 뿌려주면 될 것 같습니다.


<html>
<head>
<base href="http://teethgrinder.co.uk/open-flash-chart/"></base>
<meta http-equiv=content-type content="text/html; charset=UTF-8">
<title>Open Flash Chart - Tutorials - No Data File</title>
<link rel="stylesheet" type="text/css" title="standard Style" href="ofc.css">
</head>
<body style="font-family: verdana; font-size: 12px;">

    <div id="109299445549ac9c2e9c8b46.84997988"></div>
    <script type="text/javascript" src="js/swfobject.js"></script>
    <script type="text/javascript">
        var so = new SWFObject("open-flash-chart.swf", "ofc", "400", "250", "9", "#FFFFFF");
        so.addVariable("variables","true");
        so.addVariable("title","Paper+Mario%23comma%23+%25+complete,{font-size: 18px; color: #A0A0A0;}");
        so.addVariable("x_legend","Week+1,12,#A0A0A0");
        so.addVariable("x_label_style","10,#A0A0A0,0,1");
        so.addVariable("x_axis_steps","1");
        so.addVariable("y_label_style","10,#A0A0A0");
        so.addVariable("y_ticks","5,10,2");
        so.addVariable("x_labels","Mon,Tue,Wed,Thu,Fri,Sat,Sun");
        so.addVariable("y_min","0");
        so.addVariable("y_max","100");
        so.addVariable("x_axis_colour","#A0A0A0");
        so.addVariable("x_grid_colour","#FFFFFF");
        so.addVariable("y_axis_colour","#A0A0A0");
        so.addVariable("y_grid_colour","#FFFFFF");
        so.addVariable("tool_tip","Progress%23comma%23+%23val%23%25");
        so.addVariable("bar_sketch","50,6,#99FF00,#7030A0,%25+Complete,10");
        so.addVariable("values","50,65,70,75,80,89,100");
        so.write("109299445549ac9c2e9c8b46.84997988");
    </script>
</body>
</html>
 
function CkImageVal(value){
                            var oInput = event.srcElement;
                            var fname = oInput.value;

                            if((/(.jpg|.jpeg|.gif|.png)$/i).test(fname))
                                oInput.parentElement.children[0].src = fname;
                            else
                                alert('이미지는 gif, jpg, png 파일만 가능합니다.');

                            var imgInfo        = new Image();
                            imgInfo.onload    = img_Load;
                            imgInfo.src        = value;
                        }
                        function img_Load(){
                            var imgSrc, imgWidth, imgHeight, imgFileSize;
                            var maxFileSize;
                            maxFileSize    = 50000000;
                            imgSrc            = this.src;
                            imgWidth        = this.width;
                            imgHeight        = this.height;
                            imgFileSize    = this.fileSize;

                            if (imgSrc == "" || imgWidth > 100){
                                alert('가로 600 픽셀을 초과하는 이미지파일을 가져올 수 없습니다.');
                                return;
                            }

                            if (imgFileSize > maxFileSize){
                                alert('선택하신 그림 파일은 허용 최대크기인 ' + maxFileSize/1024 + ' KB 를 초과하였습니다.');
                                return;
                            }
                        }

복잡한 사용방법이 있고 여러 특수문자와의 조합으로 배우기가 쉽지 않아 간단한 예제를 통해 설명한다.

1. 각 문자와 숫자는 해당 문자 또는 문자열이 테스트할 문자열에 있을경우 true 가된다.


<script>
// 'a' 가 있는 문자열 모두가 TRUE (대소문자 구분)
var filter = /a/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


<script>
// "about" 가 있는 문자열 모두가 TRUE (대소문자 구분)
var filter = /about/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


2. 대소문자 구분없이 해당 문자 또는 문자열을 검색할 경우 끝에 i 를 붙인다.

<script>
// 'a' 또는 'A' 가 있는 문자열 모두가 TRUE (대소문자 구분 안함)
var filter = /a/i
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


3. 여러개의 이어지는 내용들을 검색할 경우는 '-' 를 넣어 표현한다.

<script>
// 'a' 에서 'z' 까지중 하나만 있으면 모두가 TRUE (대소문자 구분)
var filter = /[a-z]/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


4. 여러가지의 문자 또는 문자열을 검색할 경우 '|' 를 넣는다.


<script>
// 'a' 또는 'b' 또는 'c' 가 있는 문자열 모두가 TRUE (대소문자 구분)
var filter = /a|b|c/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


<script>
// 'a' 에서 'z' 까지 또는 '0' 에서 '9' 까지중 하나만 있으면 모두가 TRUE (대소문자 구분)
var filter = /[a-z]|[0-9]/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


5. 해당 문자또는 문자열이 없는 경우를 검색할 경우 브래킷('[', ']') 안에 '^' 를 넣는다.


<script>
// 'a' 에서 'z' 까지의 문자가 아닌 문자가 있을 경우 TRUE (대소문자 구분)
var filter = /[^a-z]/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


6. 문자열의 첫번째 글자가 일치해야할 경우는 '^' 를 브래킷('[', ']') 밖에 넣는다.


<script>
// 'a' 에서 'z' 까지의 문자로 시작하는 문자열일 겨우 TRUE (대소문자 구분)
var filter = /^[a-z]/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


7. 문자열의 끝쪽 글자가 해당 문자 또는 문자열과 일치해야할 경우는 '$' 를 넣는다.


<script>
// 'a' 에서 'z' 까지의 문자로 끝나는 문자열일 겨우 TRUE (대소문자 구분)
var filter = /[a-z]$/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>


8. 특수문자('\', '^', '$', '*', '+', '?', '.', '(', ')', '|', '{', '}', '[', ']')를 검색할 경우는 '\' 를 넣는다.


<script>
// '\' 가 있는 문자열일 겨우 TRUE (대소문자 구분)
var filter = /\\/
if (filter.test("some test words") == true) { alert("ok"); } else { alert("fail"); }
</script>

 
Internet Explorer 7부터는 알파 PNG 이미지를 지원하기때문에 상관이 없지만 대다수가 아직 Internet Explorer 6 버전을 사용하고 있기에 종종 부자연스러운 이미지를 발견할 수 있다. 스크립트와 CSS를 이용하여 알파 PNG 이미지의 투명도를 설정할 수 있다. (ex.이미지의 클래스는 png24로 지정한다.)

다음과 같이 CSS를 정의한 후에 png 이미지의 클레스를 지정해 주면 png 파일도 웹에서 출력할 수 있다.

<
script language="javascript">
function setPng24(obj) {
var request_os = window.navigator.userAgent;
var os_array = request_os.split(";");

if(os_array[1] != " MSIE 7.0") {
obj.width=obj.height=1;
obj.className=obj.className.replace(/png24/i,'');
obj.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+ obj.src +"',sizingMethod='image');";
obj.src='';
}

return '';
}
</script>

<style type="text/css">
.png24 {tmp:expression(setPng24(this));}
</style>

<img src="a.png" class="png24" />

/////////////////////// HTML / Javascript ////////////////////////

1. 용어 정리
 (1) HTML (Hypertext Markup Language)
  웹페이지를 표시하는 기본언어
  최신의 HTML 표준은 4.01이지만 HTML을 XML과 결합한
  XHTML(eXtensible Hypertext Markup Language)이 권고안으로 나와있다.

 (2) CSS(Cascading Style Sheets)
  CSS 는 사용자 정의의 디자인 속성, 즉 글꼴, 크기, 색상, 이벤트 등을 지정할 수 있으며
  CSS 를 사용한 모든 페이지는 기존 버전과의 호환성 되게 어떤 브라우저에서도 내용을 열
  람할 수 있다. CSS 를 이용하여 설계자는 서로 다른 화면 해상도와 브라우저 상에서, 테이
  블 없이도 동일하게 보여질 수 있는 페이지를 생성할 수 있다.

 (3) XML(eXtensible Markup Language)
  XML(eXtensible Markup Language)은 HTML이나 CSS로서 표현되지 못하는 영역을
  DTD를 이용하여 정의하여 사용자 정의의 태그를 생성하여 제작할 수 있는 메타 마크업
  언어이다.

 (4) DOM(Document Object Model)
  DOM(Document Object Model)은 웹페이지에 표현되는 모든 속성에 대해 객체화 하여
  이를 자유 자재로 사용할 수 있도록 만든 것이다.

 (5) ECMAScript (Javascript)
  자바 스크립트는 W3C 표준으로 제정된 것은 아니다. 자바 스크립트는 주석 코드를
  사용하여 비 호환성의 웹 브라우저로부터 숨겨져야 한다. 자바 스크립트는
  HTML 문서의 Head 내에 위치해야 제대로 동작한다 따라서 문서의 Body 내에 자바 스
  크립트를 위치시키는 것은 피해야 한다.


2. 웹 표준 검사
 http://validation.w3.org

3. XHTML 사용해야 하는 이유
 (1) 호환성 및 확장 가능성이 좋다.
 (2) 유지비용 감소 및 재생산성 확대
 (3) 경량의 로딩속도

4. DOCTYPE 문서형식
 (1) HTML 2.0 표준문서 형식
  <!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
 (2) HTML 3.2 표준 문서 형식
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 (3) HTML 4.01 표준 문서 형식
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
  "http://www.w3.org/TR/html4/frameset.dtd">
 (4) XHTML 1.0 표준 문서 형식
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
 (5) XHTML 1.1 표준 문서 형식
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

5. 일반 형식(Transitional)과 엄격한 형식(Strict)
 HTML 4.01 Transitional은 예전에 있었거나 없어진 태그도 지원하며,
 <font>에 지정된 스타일도 제대로 표현하여 준다.
 
 HTML 4.01 Strict은 HTML을 엄격하게 적용한다.
 <font> 태그에 적용된 스타일 보다는 CSS파일에서 지정된 스타일을 지켜 표현 해야 한다.

 가장 최상의 브라우저 호환성을 제공해 주는 문서 형식은 XHTML 1.0 Transitional을 사용하는 것이다.

6. XHTML 일반 문법 준수
 (1) 정확한 문서 구조 준수
  문서의 루트 요소는 html이 되어야 하며, 이 html 요소는 XHTML 네임스페이스를 지정해야 한다.
  <html xmlns="http://www.w3.org/1999/xhtml">
  표준 문서에는 head, title 및 body 구조 요소가 포함되어야 한다. 프레임 세트 문서에는
  head, title 및 frameset 구조 요소가 포함되어야 한다

 (2) 모든 요소는 완벽하게 중첩되어야 한다.
  <p>This is a <i>bad example.</p></i>
  <p>This is a <i>good example.</i></p>
 
 (3) 모든 속성 값은 인용 부호(“나 ‘)로 묶어야 한다.
  <a href=http://sample.com>틀린 경우</A>
  <a href="http://sample.com">맞는 경우</a>
 
 (4) 모든 요소와 속성은 소문자여야 한다.
  <A HREF="http://sample.com">틀린 경우</A>
  <a href="http://sample.com">맞는 경우</a>
 
 (5) 모든 요소는 닫아야 한다.
  XML을 사용할 수 없는 이전 브라우저와의 호환성을 위해 /> 앞에 공백이 있어야 한다
  (예: <br/>가 아니라 <br />)
 
 (6) 모든 속성값은 속성이 함께 선언되어야 한다.
  <option value="wrong" selected>틀린 경우</option>
  <option value="right" selected="selected">맞는 경우</option>
 
 (7) 모든 script 및 style 요소에는 type 속성이 포함되어야 한다.
  <script type="text/javascript” language="javscript"></script>
  <style type="text/css"></style>
 
 (8) 모든 img 및 area 요소에는 alt 속성이 포함되어야 한다.
 
 (9) 모든 SCRIPT내의 태그는 Escape 시켜야 한다.
  <script type="text/javascript">
  <!--
  // 틀린 표현!
  document.write("</P>");
  // -->
  </script>

  <script type="text/javascript">
  <!--
  // 맞는 표현!
  document.write("<\/P>");
  // -->
  </script>

  <script type="text/javascript">
  <![CDATA[
  ... <h1>데이터</h1> ...
  ]]>
  </script>

 (10) 모든 문서 내 URL에서 &를 쓰면 안 된다.
  <!.에러! --> <a href="foo.cgi?chapter=1&section=2">...</a>
  <!.적합! --> <a href="foo.cgi?chapter=1&amp;section=2">...</a>
 
 보너스
 테이블 구성시 <table><form></form></table> 식으로 form의 여백을 일부러
 없애는 경우가 있는데 이것은 css로 바로 해결 가능.
 form { margin: 0; }

7. CSS
 http://csszengarden.com
 http://phonophunk.com/

 (1) CSS의 선언
  <1> Selector 와 선언부 (p.text : Selector, {} : 선언부)
   p.text {
    margin: 0;
   }
  <2> Selector는 ,로 구분할 수 있다.  
   p.text,
   span.name {
    color: #666;
   }
  <3> 일반 선택자
   - 공용 선택자 * : 모든 태그 지정
    div.search * {
     vertical-align: middle
    } --> div.search 안의 모든 엘리먼트가 다 적용
   - 타입 선택자 A : 태그 A 지정
   - 클래스 선택자 .A : 클래스가 A인 태그를 지정
   - ID 선택자 #A : 아이디가 A인 태그를 지정
  <4> 복합 선택자
   - 하위 선택자 A B : 태그 A로 감싸져 있는 모든 태그 B 지정
    <ul id="list">
     <li><a href="list.html?id=34&amp;type=blah">item 34</a></li>
     <li><a href="list.html?id=35&amp;type=blah">item 35</a></li>
     ...
     ...
     <li><a href="list.html?id=99&amp;type=blah">item 99</a></li>
    </ul>
    --> a 태그에 속성 지정시
    ul#list a:link,
    ul#list a:visited {
     color: #999;
    }
    ul#list a:hover,
    ul#list a:active {
     color: #000;
    }
    --> 한방에 해결
   - 자식 선택자 A > B : 태그 A로 감싸져 있는 바로 하위단계 B만 지정
    <ul class="depth1">
     <li>
      <a href="about.html">Company</a>
      <ul class="depth2">
       <li>
        <a href="overview.html">Overview</a>
       </li>
       <li>
        <a href="ceo.html">Ceo.html</a>
       </li>
      </ul>
     </li>
    </ul>
    ul.depth1 li {
     background: #f9f9f9;
     border-bottom: 1px solid #ddd;
    }
    ul.depth1>li {
     background: #f9f9f9;
     border-bottom: 1px solid #ddd;
    }
   - 인접 선택자 A + B : 태그 A와 B가 연속으로 나와 있는 것을 지정
    <h2>브라우져 워</h2>

    <p>웹스탠다드를 보다 잘 이해하기 위해서는 브라우져 워에 대해서 짚어볼 필요가
    있습니다.</p>

    <h2>어쩌고 저쩌고</h2>

    <p>또다시 어쩌고 저쩌고</p>

    --> 제목 뒤 첫글자만 크게 하고 싶다면??
    h2+p:first-letter {
     float: left;
     font-size: 2.2em;
    }
  <5> 가상 클래스 선택자
   - :first-child선택자 A:first-child : 태그 A로 감싸져 있는 가장 처음 태그 지정
   - 언어선택자 A:lang(B) : 태그 A중 언어가 B인 태그 지정
   - 링크선택자 A:link : 태그 A중 링크가 걸려있는 것 지정
          A:visited : 태그 A중 링크가 걸려있고, 사용자가 이미 클릭한 태그 지정
   - 동적선택자 A:active : 태그 A중 사용자가 마우스를 누르고 있는 태그 지정
       A:hover : 태그 A중 사용자가 마우스 포인터를 위에 올려놓은 태그 지정
       A:focus : 태그 A중 사용자의 키보드 입력을 받는 태그 지정
  <6> 동적 선택자
   - :first-line선택자 A:first-line : 태그 A의 문단중 첫번째 줄 지정
   - :first-letter선택자 A:first-letter : 태그 A의 문단중 첫번째 글자 지정
   - :before선택자 A:before : 태그 A의 문단 앞을 지정
   - :after선택자 A:after : 태그 A의 문단 뒤를 지정

 (2) CSS 선언 방법
  <1> 외부 선언 (external css) - 우선순위가 낮다.
   <link rel="stylesheet" type="text/css" href="myCss.css" />
  <2> 엘리먼트에 직접 선언 (inline css)
   <div style="padding: 10px; border: 1px solid #eee;">
    <p>contents</p>
   </div>
  <3> 사용자 정의 스타일 (user defined css)
   가장 우선 순위가 높은 선언으로 웹페이지 제작자가 선언하는 것이 아니라 웹사이트를 이
   용하는 사용자가 직접 자신에게 맞는 스타일을 선언하는 방법이다.
 
 (3) CSS 적용의 체크 포인트 4가지
  <1> XHTML이 표준 문법이어야 한다.
  <2> XHTML 문서가 의미와 구조적으로 구성되어야 한다.
  <3> CSS가 표준 문법이어야 한다.
  <4> CSS를 표준대로 잘 구현한 브라우져를 이용해야 한다.

 (4) CSS Editor Firefox plugin
  <1> Web Developer 확장 기능
  <2> HTML Tidy

8. DOM / Script
 문서 객체 모델(DOM; Document Object Model)은 HTML내에 들어 있는 요소를 구조화
 객체 모델로 표현하는 형식이다. DOM은 플랫폼/언어 중립적으로 구조화된 문서를
 표현하는 W3C 표준 모델이 기반이 된다.

 (1) 객체 접근방법
  <1> document.getElementById(aId)
  <2> document.getElementByTagName(aTagName)
  <3> 기존방식 밖에 지원안하는 IE 지원
   function getObject(objectId) {
    if(document.getElementById && document.getElementById(objectId) {
     return document.getElementById(objectId); // check W3C DOM
    }
    else if (document.all && document.all(objectID) {
     return document.all(objectID); // IE4
    }
    else if (document.layers && document.layers[objectID] {
     return document.layer[objectID]; // NN4
    }
    else {
     return false;
    }
   }
 (2) 객체 사용 방법
  구성요소의 내용을 바꾸거나 수정하는 innerText, innerHTML, outerText, outerHTML을
  사용하는 것은 원래 잘못된 것이다. 왜냐하면 이는 W3C DOM 표준이 아니고 MS DOM 이기 때문이다.
  firefox에서는 innerHTML만이 지원된다. 나머지는 지원불가!
 
  속성 사용
  1. x.id 나 x.style 같은 방법으로 먼저 속성을 찾는다.
  2. 값이 나오지 않으면 x.getAttribute(“align”)나 x.getAttributeNode(“align”).value 로 찾는다.
  3. 그래도 나오지 않으면 다른 속성 인터페이스를 시도하되, attributes[]는 절대 사용하지 않는다.
 

런타임 오류
스크립트에서 시스템이 실행할 수 없는 동작을 수행하려고 할 때 발생하는 오류입니다.
런타임 오류는 해당 스크립트가 실행되는 동안 또는 변수식이 평가되거나 메모리가 동적으로 할당될 때 발생합니다.
오류 번호 설명
5029 배열의 길이는 유한한 양수값이어야 합니다
5030 배열의 길이는 유한한 양수값이어야 합니다
5028 Array 또는 arguments 개체가 필요합니다
5010 Boolean이 필요합니다
5003 함수 결과에 할당할 수 없습니다
5000 'this'에 할당할 수 없습니다
5006 날짜 개체가 필요합니다
5015 열거형 개체가 필요합니다
5022 예외적인 흐름으로 잡을 수가 없습니다
5020 정규식에 ')'가 필요합니다
5019 정규식에 ']'가 필요합니다
5023 함수에 유효한 표준 개체가 없습니다
5002 함수가 필요합니다
5008 잘못된 할당
5021 잘못된 범주의 문자 집합입니다
5014 JScript 개체가 필요합니다
5001 숫자가 필요합니다
5007 개체가 필요합니다
5012 개체 구성원이 필요합니다
5016 정규식 개체가 필요합니다
5005 문자열이 필요합니다
5017 정규식에서 구문 오류가 발생하였습니다
5026 소수부 자리수가 범위를 초과하였습니다
5027 정밀도가 범위를 초과하였습니다
5025 디코딩될 URI가 유효한 인코딩이 아닙니다
5024 인코딩될 URI가 유효하지 않은 문자를 포함하고 있습니다
5009 정의되지 않은 식별자
5018 예기치 않은 수량사
5013 VBArray가 필요합니다
구문 오류
스크립트에서 문법 규칙을 하나 이상 위반할 경우 발생하는 오류입니다.
구문 오류는 프로그램이 실행되기 전에 프로그램을 컴파일하는 단계에서 발생합니다.
오류 번호 설명
1019 루프 밖에서는 'break'를 사용할 수 없습니다
1020 루프 밖에서는 'continue'를 사용할 수 없습니다
1030 조건부 컴파일이 해제되었습니다
1027 'switch' 문에서 'default'는 한번만 나타날 수 있습니다.
1005 '('가 필요합니다
1006 ')'가 필요합니다
1012 '/'가 필요합니다
1003 ':'가 필요합니다
1004 ';'가 필요합니다
1032 '@'가 필요합니다
1029 '@end'가 필요합니다
1007 ']'가 필요합니다
1008 '{'가 필요합니다
1009 '}'가 필요합니다
1011 '='가 필요합니다
1033 'catch'가 필요합니다
1031 상수가 필요합니다
1023 16진수가 필요합니다
1010 식별자가 필요합니다
1028 식별자나 문자열 또는 숫자가 필요합니다
1024 'while'이 필요합니다
1014 유효하지 않은 문자입니다
1026 레이블을 찾을 수 없습니다
1025 레이블이 재정의되었습니다
1018 함수 밖의 'return' 문장
1002 구문 오류
1035 동일한 원본 줄에 수식이 뒤따라야 합니다
1016 종결되지 않은 주석입니다
1015 종결되지 않은 문자열 상수입니다

/*-----------------------------------------------------------------------------*/
// 특수문자 체크
// - obj : form name
/*-----------------------------------------------------------------------------*/
function inputCheckSpecial(obj){

 var ft = "true";
  obj = obj.elements;
 for (var i = 0; i < obj.length; i++){

  if( obj[i].type == "text" ||obj[i].type == "password"){

    var strobj = obj[i].value; //입력값을 담을변수.
    re = /[~!@\#$%<>^&*\()\-=+_\']/gi;
    if(re.test(strobj)){
   alert("특수문자는 입력하실수 없습니다.");
   obj[i].value=strobj.replace(re,"");
   obj[i].focus();
   ft += ",false";
    }else {
   ft += ",true";
    }//end if

  }//end if
 }//end for

 if (ft.indexOf("false")!=-1){
  return false;
 }else{
  return true;
 }
}

<script type="text/javascript" >
var childWindow1;

//보고서팝업
function openRpt(frm){
 childWindow1 = window.open("","srchRpt","scrollbars=no,toolbar=no,resizable=no,width=420,height=510,left=0,top=0");
 //alert(childWindow1);
 frm.target = "srchRpt";
 frm.action = "/fs/dis/com/DISRptSrch.jsp"
 frm.method="post";
 frm.submit();
 childWindow1.focus();
}


/*-- 팝업 닫기--*/
function windowClose() {
 try {
  if(childWindow1) childWindow1.close();
 }
 catch(e) {}


 try {
  if(childWindow2) childWindow2.close();
 }
 catch(e) {}
}
window.attachEvent("onunload",windowClose);

javascript 에서 배열을 사용할때 유의점!


배열의 length는 배열의 길이가 2이상일때만 구해올수 있다.

1개이하일때는 배열이 아닌 Object로 인식하기 때문이다.


1개이하일때는 undefined 처리를 해줘야 한다.


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

sample

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

  var chks;
 var frame = document.getElementById(obj);
  chks = document.all.popChk;


if(chks.length == undefined && chks.value!=''&& chks.value!=null){
   var divID =  chks.value;
   var emt = document.getElementById(divID);
   emt.removeNode(true);
 }else{
  for(i=0; i<chks.length; i++) {  
    if(chks[i].checked) {  
   var divID =  chks[i].value;
   var emt = document.getElementById(divID);
   emt.removeNode(true);
   i--;
    } //end of if
   }//end of for
  }//end of ifelse

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

document.all 에서 id값들을 가져오기

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

 function viewElement()
 {
  var coll = document.all.tags("span");
  if (coll!=null)
  {
   for (i = 0; i < coll.length; i++)
     alert(coll[i].id);  
  }
 }



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

searchForm 에 있는 태그 이름들 가져오기

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

function setInfo()
{
 var es = document.searchForm.elements;
 for (var i = 0; i < es.length; i++)
 {
  var tname = es[i].tagName.toLowerCase();
 
  var oname = es[i].name;
  var otext = "";
  if (tname == "select")
  {
   var tobj = eval("document.searchForm." + oname);
   if (tobj.options.length < 1)
    continue;
   otext = tobj.options[tobj.selectedIndex].text;
  }
  else
   otext = es[i].value;
  try
  { /*검색조건*/
   eval("document.all.info_" + oname).innerText = otext;

   /*레포트출력검색조건*/
   eval("document.searchForm.rpt_" + oname).value = otext;
  }
  catch (e)
  {}//end of try catch
 }//end of for
}




---------------------응용-------------------------------------

function clearDetail(){
 var es = document.all.tags("span");
 if (es!=null)
 {
  for (var i = 0; i < es.length; i++)
  {
   var oname = es[i].id;
   try
   {
    if(oname.indexOf('detail_') > -1){
     document.getElementById(oname).innerHTML = "&nbsp;";
    }
   }
   catch (e)
   {}//end of try catch

  }//end of for
 }//end of if
}

보통 로그인할때 아이디를 저장하는 기능 입니다.

다음번 로그인 할때 아이디가 자동으로 입력되도록 쿠키로 설정하는 것입니다.


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


<html>
<head>
<script language="javascript">
function setCookie (name, value, expires) {
  document.cookie = name + "=" + escape (value) +
    "; path=/; expires=" + expires.toGMTString();
}

function getCookie(Name) {
  var search = Name + "="
  if (document.cookie.length > 0) { // 쿠키가 설정되어 있다면
    offset = document.cookie.indexOf(search)
    if (offset != -1) { // 쿠키가 존재하면
      offset += search.length
      // set index of beginning of value
      end = document.cookie.indexOf(";", offset)
      // 쿠키 값의 마지막 위치 인덱스 번호 설정
      if (end == -1)
        end = document.cookie.length
      return unescape(document.cookie.substring(offset, end))
    }
  }
  return "";
}
function saveid(form) {
  var expdate = new Date();
  // 기본적으로 30일동안 기억하게 함. 일수를 조절하려면 * 30에서 숫자를 조절하면 됨
  if (form.checksaveid.checked)
    expdate.setTime(expdate.getTime() + 1000 * 3600 * 24 * 30); // 30일
  else
    expdate.setTime(expdate.getTime() - 1); // 쿠키 삭제조건
  setCookie("saveid", form.id.value, expdate);
}
function getid(form) {
  form.checksaveid.checked = ((form.id.value = getCookie("saveid")) != "");
}
</script>
</head>
<body onLoad="getid(document.mainform)">
<form name=mainform>
아이디 <input type=text name=id>
암호 <input type=password name=pw>
<input type=checkbox name=checksaveid onClick="saveid(this.form)">아이디 기억
</form>
</body>
</html>

EUC-KR<=>UTF-8 상호변환 하기

<?
# UTF 로 무조건 변환
function change_to_utf($utfStr) {
  if (iconv("UTF-8","UTF-8",$utfStr) == $utfStr) {
    return $utfStr;
  }
  else {
    return iconv("EUC-KR","UTF-8",$utfStr);
  }
}

# UTF => EUC-KR로 변환
function iconv_to_euc_kr($get_data) {
  $work_unit = 50;

  $init_size = strlen($get_data);

  $result_data = "";

  $count = 0;

  for ( $i = 0 ; $i < $init_size ; $i++ ) {
    $cur_char = substr($get_data,$i,1);

    $t = ord($cur_char);
    if ( $t == 9 || $t == 10 || (32 <= $t && $t <= 126) ) {
      $tn = 1;
    }
    else if ( 194 <= $t && $t <= 223 ) {
      $tn = 2;
    }
    else if ( 224 <= $t && $t < 239 ) {
      $tn = 3;
    }
    else if ( 240 <= $t && $t <= 247 ) {
      $tn = 4;
    }
    else if ( 248 <= $t && $t <= 251 ) {
      $tn = 5;
    }
    else if ( $t == 252 || $t == 253 ) {
      $tn = 6;
    }
    else {
      $tn = 1;
    }

    if ( $work_unit < $tn ) {
      break;
    }

    if ( $count + $tn > $work_unit ) {
      $temp_data = iconv("utf-8","euc-kr",$work_string);
      $result_data .= $temp_data;

      $work_string = "";
      $i--;
      $count = 0;
    }
    else {
      for ( $j = 0 ; $j < $tn ; $j++ ) {
        $work_string .= $cur_char;
        $i++;
        $count++;
        $cur_char = substr($get_data,$i,1);
      }
      $i--;
    }
  }

  if ( $work_string ) {
    $temp_data = iconv("utf-8","euc-kr",$work_string);
    $result_data .= $temp_data;
  }

  return $result_data;
}

# ex.

# 수신된 메일로부터 폼값을 받을때 수신된 메일의 charset이 euc-kr이 아닌 UTF8로 오는 경우,

# 일단 무조건 UTF8로 변환한 후 EUC-KR로 재변환하여 처리해야만 한글이 깨지지 않고

# 정상적으로 표출됩니다.

# Usage.
# $fromName = change_to_utf($fromName);
# $fromName = iconv_to_euc_kr($fromName);

?>


/**
* UTF-8=>한글 코드페이지[949]로 변환  AJAX에서 유니코드 문자 오류
*/
function utf8_euckr(&$item, $key, $prefix = ''){
    if(is_array($item)) array_walk($item, 'utf8_euckr');
    else $item=iconv('UTF-8', 'CP949',$item);
}
/**
* 한글 코드페이지[949] => UTF-8로 변환  AJAX에서 유니코드 문자 오류
*/
function euckr_utf8(&$item, $key, $prefix = ''){
    if(is_array($item)) array_walk($item, 'euckr_utf8');
    else $item=iconv('CP949', 'UTF-8',$item);
}
/**
* 입력값
*/
@array_walk($_POST, 'utf8_euckr');

/**
* 결과값 변환
*/
@array_walk($Result, 'euckr_utf8');

<html>
<head>
<title>레이어 셀렉트메뉴</title>
<script type="text/javascript" src="http://www.blog4u.kr/attach/1/cfile8.uf@1336903C504870822B3785.js">
</script>
<style>
.selectBoxSelectedAreaGlobal {color:#626262; font-size:12px; font-family:dotum; font-weight:normal; background-color:#f5f5f5; padding-top:2px; line-height:17px; padding-left:5px; letter-spacing:-1px;}
.selectBoxSelectedAreaFocusGlobal {color:#626262; font-size:12px; font-weight:normal; font-family:dotum; background-color:#f5f5f5; padding-top:2px; line-height:17px; padding-left:5px; letter-spacing:-1px;}
.selectBoxOptionGlobal {color:#626262; font-size:12px; font-family:dotum; font-weight:normal; background-color:#f5f5f5; padding-top:2px; line-height:17px; padding-left:5px; letter-spacing:-1px;}
.selectBoxOptionOverGlobal {color:#626262; font-size:12px; font-family:dotum; font-weight:normal; background-color:#e6e6e6; padding-top:2px; line-height:17px; padding-left:5px; letter-spacing:-1px;}
.selectBoxOptionInnerLayer {overflow:auto;background-color:#f5f5f5;
    scrollbar-face-color:#F3F3F3;
    scrollbar-shadow-color:#6C6C6C;
    scrollbar-highlight-color:#FFFFFF;
    scrollbar-3dlight-color:#C9C9C9;
    scrollbar-darkshadow-color:#FFFFFF;
    scrollbar-track-color:#F3F3F3;
    scrollbar-arrow-color:#000000;
}
</style>
</head>
<body>
    <select id="leftSelectBoxGlobal" style="width:159px;height:21px;display:none;">
        <option value="1">서명</option>
        <option value="2">저자</option>
        <option value="3">출판사</option>
    </select>
    <script>
        makeSelectBoxGlobal("leftSelectBoxGlobal", "selectBoxSelectedAreaGlobal", "#e6e6e6", "http://www.blog4u.kr/attach/1/cfile8.uf@12669C3A50487083080605.gif", "selectBoxOptionGlobal", "selectBoxSelectedAreaFocusGlobal", "selectBoxOptionOverGlobal");
</script>
</body>
</html>  
사용자 삽입 이미지
소스의 기본-샵의 레이아웃 전체 사이즈가 900픽셀이고 자동스크롤되면서 슬라이드되는 것을 좌측과 우측에 동시 적용이 되며, 좌측과 우측에 나타날 내용의 폭을 48픽셀로 하였슴(이 픽셀값은 자신의 샵에 맞게 수정 가능).
스킨폴더의 head.html 파일의 임의의 곳에 추가하시면 됩니다.

[소스 시작]
[code2]<!--왼쪽스크롤시작-->
<script language="JavaScript">
<!--
// 스크롤메뉴
var bNetscape4plus = (navigator.appName == "Netscape" && navigator.appVersion.substring(0,1) >= "4");
var bExplorer4plus = (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion.substring(0,1) >= "4");

function always_pos1()
{
var yMenuFrom, yMenuTo, yButtonFrom, yButtonTo, yOffset, timeoutNextCheck;

if ( bNetscape4plus ) { // 네츠케이프 용 설정
yMenuFrom = document["scrollmenu1"].top;
yMenuTo = top.pageYOffset + 100; // 화면 위쪽으로 부터의 위치
}
else if ( bExplorer4plus ) { // 익스플로러 용 설정
yMenuFrom = parseInt (scrollmenu1.style.top, 10);
yMenuTo = document.body.scrollTop + 100; // 화면 위쪽으로 부터의 위치
}

timeoutNextCheck = 500;

if ( Math.abs (yButtonFrom - (yMenuTo + 152)) < 6 && yButtonTo < yButtonFrom ) {
setTimeout ("always_pos1()", timeoutNextCheck);
return;
}

if ( yButtonFrom != yButtonTo ) {
yOffset = Math.ceil( Math.abs( yButtonTo - yButtonFrom ) / 10 );
if ( yButtonTo < yButtonFrom )
yOffset = -yOffset;

if ( bNetscape4plus )
document["divLinkButton"].top += yOffset;
else if ( bExplorer4plus )
divLinkButton.style.top = parseInt (divLinkButton.style.top, 10) + yOffset;

timeoutNextCheck = 10;
}
if ( yMenuFrom != yMenuTo ) {
yOffset = Math.ceil( Math.abs( yMenuTo - yMenuFrom ) / 20 );
if ( yMenuTo < yMenuFrom )
yOffset = -yOffset;

if ( bNetscape4plus )
document["scrollmenu1"].top += yOffset;
else if ( bExplorer4plus )
scrollmenu1.style.top = parseInt (scrollmenu1.style.top, 10) + yOffset;

timeoutNextCheck = 10;
}

setTimeout ("always_pos1()", timeoutNextCheck);
}
function OnLoad()
{
var y;

// 프레임 에서 벗어나게 하는 함수입니다. 프레임에 넣으려면 삭제하세요
if ( top.frames.length )
// top.location.href = self.location.href;

// 페에지 로딩시 포지션
if ( bNetscape4plus ) {
document["scrollmenu1"].top = top.pageYOffset + 100;
document["scrollmenu1"].visibility = "visible";
}
else if ( bExplorer4plus ) {
scrollmenu1.style.top = document.body.scrollTop + 100;
scrollmenu1.style.visibility = "visible";
}

always_pos1();
return true;
}
// -->
</script>
<!--왼쪽스크롤끝-->
<!---left banner start-->
<div id="scrollmenu1" style="position:absolute;right:expression(((document.body.clientWidth+900)/2)-0);top:100px;z-index:101">
<table width="48" border=0 cellpadding=0 cellspacing=0>
<tr>
<td>
<!-- 좌측에 보여주고자 하는 내용-->
</td>
</tr>
</table>
<script>OnLoad();</script>
</div>
<!--left banner stop--->

<!--오른쪽스크롤시작-->
<script language="JavaScript">
<!--
// 스크롤메뉴
var bNetscape4plus = (navigator.appName == "Netscape" && navigator.appVersion.substring(0,1) >= "4");
var bExplorer4plus = (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion.substring(0,1) >= "4");

function always_pos2()
{
var yMenuFrom, yMenuTo, yButtonFrom, yButtonTo, yOffset, timeoutNextCheck;

if ( bNetscape4plus ) { // 네츠케이프 용 설정
yMenuFrom = document["scrollmenu2"].top;
yMenuTo = top.pageYOffset + 100; // 화면 위쪽으로 부터의 위치
}
else if ( bExplorer4plus ) { // 익스플로러 용 설정
yMenuFrom = parseInt (scrollmenu2.style.top, 10);
yMenuTo = document.body.scrollTop + 100; // 화면 위쪽으로 부터의 위치
}

timeoutNextCheck = 500;

if ( Math.abs (yButtonFrom - (yMenuTo + 152)) < 6 && yButtonTo < yButtonFrom ) {
setTimeout ("always_pos2()", timeoutNextCheck);
return;
}

if ( yButtonFrom != yButtonTo ) {
yOffset = Math.ceil( Math.abs( yButtonTo - yButtonFrom ) / 10 );
if ( yButtonTo < yButtonFrom )
yOffset = -yOffset;
if ( bNetscape4plus )
document["divLinkButton"].top += yOffset;
else if ( bExplorer4plus )
divLinkButton.style.top = parseInt (divLinkButton.style.top, 10) + yOffset;
timeoutNextCheck = 10;
}
if ( yMenuFrom != yMenuTo ) {
yOffset = Math.ceil( Math.abs( yMenuTo - yMenuFrom ) / 20 );
if ( yMenuTo < yMenuFrom )
yOffset = -yOffset;
if ( bNetscape4plus )
document["scrollmenu2"].top += yOffset;
else if ( bExplorer4plus )
scrollmenu2.style.top = parseInt (scrollmenu2.style.top, 10) + yOffset;
timeoutNextCheck = 10;
}
setTimeout ("always_pos2()", timeoutNextCheck);
}
function OnLoad()
{
var y;
// 프레임 에서 벗어나게 하는 함수입니다. 프레임에 넣으려면 삭제하세요
if ( top.frames.length )
// top.location.href = self.location.href;
// 페이지 로딩시 포지션
if ( bNetscape4plus ) {
document["scrollmenu2"].top = top.pageYOffset + 100;
document["scrollmenu2"].visibility = "visible";
}
else if ( bExplorer4plus ) {
scrollmenu2.style.top = document.body.scrollTop + 100;
scrollmenu2.style.visibility = "visible";
}
always_pos2();
return true;
}
// -->
</script>
<!--오른쪽스크롤끝-->
<!---right banner start-->
<div id="scrollmenu2" style="position: absolute; left: expression(((document.body.clientWidth+900)/2)-0); top:100px;z-index:102">
<table width="48" border=0 cellpadding=0 cellspacing=0>
<tr>
<td>
<!-- 우측에 보여주고자 하는 내용-->
</td>
</tr>
</table>
<script>OnLoad();</script>
</div>
<!--right banner stop>[/code2]
[editableText.js]

function createEditor(callback){
  var editor = new Editor();
  editor.callback = callback;

  try{
      document.addEventListener('click',clickEventHandler,false);
  }catch(e){
      document.attachEvent('onclick',clickEventHandler);
  }

  return editor;
}
function clickEventHandler(e){
  var evt = e || window.event;
  var target;

  if(evt.target){
      target = evt.target;
  }else{
      target = evt.srcElement;
  }

  if(target.className.search('editable') > -1){
      editor.editing(target);
  }
}

function Editor(){
  this.autosave = false;
  this.source = null;
  this.callback = null;
  this.container = null;
  this.frm = document.createElement('INPUT');
  this.frm.className = 'editor';
  this.frm.model = this;

  this.frm.onkeydown = function(e){
      var evt = e || window.event;

      if(evt.keyCode == 13){
          try{
              evt.preventDefault();
          }catch(ex){
              evt.returnValue = false;
          }

          this.model.complete();
      }
  }

  this.frm.onblur = function(e){
      if(this.model.autosave == true){
            this.model.complete();
        }else{
            this.model.cancel();
        }
  }
}

Editor.prototype.editing = function(obj){
  try{
      this.container = obj;

      if(obj.hasChildNodes() == false){
          obj.appendChild(document.createTextNode(''));
      }

      this.source = obj.firstChild;
      this.frm.value = this.source.nodeValue;
      this.frm.style.width = '100%';

      if(this.container.style.textAlign != undefined && this.container.style.textAlign != ''){
            this.frm.style.textAlign = this.container.style.textAlign;
        }else if(this.container.align != undefined && this.container.align != ''){
            this.frm.style.textAlign = this.container.align;
        }else{
            this.frm.style.textAlign = 'left';
      }

      this.container.replaceChild(this.frm,this.source);
      this.frm.focus();
      this.frm.value += '';
  }catch(e){
  }
}

Editor.prototype.cancel = function(){
  this.finish();
}

Editor.prototype.complete = function(){
  this.save();
  this.finish();

  if(this.callback instanceof Function){
      this.callback(this.container);
  }else{
  }
}

Editor.prototype.finish = function(){
  this.container.replaceChild(this.source,this.frm);
}

Editor.prototype.save = function(){
  this.source = document.createTextNode(this.frm.value);
}


모듈을 페이지에 로드시키고 에디터 객체를 생성하면 준비는 끝.

<script type="text/javascript" src="editableText.js"></script>
<script type="text/javascript">
var editor = createEditor(callback);

function callback(obj){
}
</script>


사용자가 문서의 텍스트 부분을 클릭하면 텍스트 노드를 담고있는 container 객체의 className 속성에 'editable' 가 있는지 확인한 후 에디터 객체(INPUT)에 텍스트를 전달하고 텍스트노드와 에디터를 바꿔치기한다.

에디터는 싱글턴(singleton)으로 하나의 에디터가 문서 전역에서 동작한다.

autosave 속성이 true로 설정되면 에디터에서 수정후 포커스가 다른 곳으로 이동하면 자동으로 수정한 내용이 원본 텍스트 노드에 그대로 적용이 되고 반대로 false면 원 상태로 되돌린다.
autosave를 적용하지 않으면 사용자는 데이터 수정 후 엔터키를 눌러야 수정한 내용이 반영된다.

callback 함수를 지정하면 save() 메서드를 실행 후 callback 함수를 호출한다.
xmlHttpRequest 객체를 사용할 경우 동적으로 DB의 내용을 수정 할 수 있다.

원래는 source를 <span>태그에만 할당 하려했으나 셀작업에 쓰는게 더 좋을 것 같아서 'edtiable'을 className으로 갖는 모든 객체로 수정하였다.
하지만 변경 후 맘에 안드는 것이, 원글 너비(offsetWidth)의 반영이다.
<span>,<div>등 block 객체에 edtiable 을 적용하면 원글의 사이즈에 맞게 에디터의 사이즈를 조절할 수 있는 반면 테이블의 셀(TD)에 적용 할 경우 테이블 셀 크기에 맞춰버리니 맞춤 사이즈는 포기할 수 밖에 없다....
방법을 아시는 분은 코멘트를 부탁...^^;


*주의*
Editor는 멀티라인 편집을 지원하지 않는다.
<span>,<td>,<div>,<p> 의 엘리먼트에서 오직 가장 처음에 위치한 텍스트 노드를 편집 할 수 있다.
멀티라인 편집을 위해 Editor 객체에 에디터를 input과 textarea 두개로 구분하여 childNodes.lenth로 멀티라인 여부를 판별한 후 해당 엘리먼트에 맞는 에디터를 쓰게끔 리펙토링을 시도하였으나,
editing() 메서드와 finish() 메서드에서 replaceChild를 쓸 수 없고,
텍스트 노드 사이의 태그를 검출해야 하며, 멀티라인의 경우 줄바꿈 처리를 하는 등 코드가 복잡해지는 관계로 단문 인라인 엘리먼트에 이 스크립트를 사용할 것을 당부하는 것으로 대신한다.

'Web(웹) Study > Java Script' 카테고리의 다른 글

레이어 셀렉트메뉴  (0) 2008.07.15
가로정렬 좌우 스크롤 배너  (0) 2008.07.09
HTC for rainEditor v 10(위즈윅 웹편집기)  (0) 2008.07.09
OFCJS (Open Flash Chart)  (2) 2008.07.09
아이프레임 크기 자동조절  (0) 2008.07.03

HTC for rainEditor v 10(위즈윅 웹편집기)



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

- Install files & The Code


레인에디터 HTC 서비스를 위해서는 몇가지 파일이 필요합니다.
1. [ bindings.xml ]- FireFox 용 HTC binding file
2. [ moz-behaviors.xml ] - FireFox 용 HTC behaviors
3. [ raineditor.htc ]- 레인에디터 HTC 파일
4. 당 서비스는 비상업용 사이트에서는 이용가능하나 상업용 사이트는 사용을 불허합니다.


<script TYPE="text/JavaScript" LANGUAGE="JavaScript1.2"
    SRC="http://file.cafen.net/editor/prototype.js"></script>
<script TYPE="text/JavaScript" charset="euc-kr" LANGUAGE="JavaScript1.2"
    SRC="http://file.cafen.net/editor/rain_util.js"></script>
<script TYPE="text/JavaScript" LANGUAGE="JavaScript1.2"
    SRC="http://file.cafen.net/editor/swfupload.js"></script>
<script TYPE="text/JavaScript" charset="utf-8" LANGUAGE="JavaScript1.2"
    SRC="http://file.cafen.net/editor/xmlhttp.js"></script>
<script TYPE="text/JavaScript" charset="euc-kr" LANGUAGE="JavaScript1.2"
    SRC="http://file.cafen.net/editor/RainEditor_v10s.js"></script>

<style>
.raineditor {
    behavior: url(/HTCCSS/raineditor.htc); /* for IE */
    -moz-binding: url(/HTCCSS/bindings.xml#raineditor.htc); /* for FireFox */
}
</style>


- 짧은 메모형 에디터


사용자 삽입 이미지
 

<textarea name=contents01 class="editorhtc" skin=blue toolbar=small canbenull=true width=450 height=100>
<font size=3>에디<u>터</u> <b>테</b>스</font>터
</textarea>


- 단순형 에디터


사용자 삽입 이미지
 

<textarea name=contents01 class="editorhtc" skin=black toolbar=simple canbenull=true width=550 height=200>
<font size=3>에디<u>터</u> <b>테</b>스</font>터
</textarea>


- 무첨부 에디터


사용자 삽입 이미지
 

<textarea name=contents01 class="editorhtc" skin=black toolbar=simple canbenull=true width=550 height=200>
<font size=3>에디<u>터</u> <b>테</b>스</font>터
</textarea>


- 기본형 에디터


사용자 삽입 이미지
 

<textarea name=contents01 class="editorhtc" skin=gray toolbar=base canbenull=true width=550 height=200>
<font size=3>에디<u>터</u> <b>테</b>스</font>터
</textarea>


- 고급형 에디터


사용자 삽입 이미지
 

<textarea name=contents01 class="editorhtc" skin=whitenblack toolbar=full canbenull=true width=550 height=200>
<font size=3>에디<u>터</u> <b>테</b>스</font>터
</textarea>

HTC for OFCJS
- (Open Flash Chart for Javascript)


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

- Install files & The Code


오픈플레쉬 차트 서비스를 위해서는 몇가지 파일이 필요합니다.
1. [ bindings.xml ]- FireFox 용 HTC binding file
2. [ moz-behaviors.xml ] - FireFox 용 HTC behaviors
3. [ ofcjs.htc ]- 오픈 플레쉬 차트 HTC 파일
4. 당 서비스는 비상업용 사이트에서는 이용가능하나 상업용 사이트는 사용을 불허합니다.


<script type="text/javascript" src="http://chart.cafen.net/JS/swfobject.js"></script>
<script type="text/javascript" charset="utf-8" src="http://chart.cafen.net/JS/rainOpenSWFChart.js"></script>

<style>
.charthtc {
    behavior: url(css/ofcjs.gif);
    -moz-binding: url(css/bindings.xml#ofcjs.htc);
}
</style>

- [ Charts ] - Data

 
사용자 삽입 이미지


<div class="charthtc" style="width:680px;height:200px">
<c_title text='Many data lines' cstyle='{font-size: 20px; color: #736AFF}'></c_title>
<c_data data='15,18,14,14,14,16,19,14,15,18,15,14'></c_data>
<c_data data='9,9,12,9,10,10,12,8,13,11,13,11'></c_data>
<c_data data='6,1,7,1,2,1,4,2,2,7,2,4'></c_data>
<c_line text='Page views' color='#9933CC' size=10 width=2></c_line>
<c_linedot text='Downloads' color='#CC3399' size=10 width=3 dotsize=5></c_linedot>
<c_linehollow text='Bounces' color='#80a033' size=10 width=2 dotsize=4></c_linehollow>
</div>


- [ Charts ] - Bar Chart


사용자 삽입 이미지
 

<div class="charthtc" style="width:680px;height:200px">
<c_title text='Bar Chart' cstyle='{font-size: 20px;}'></c_title>
<c_data data='5,8,6,5,9,7,5,9,9'></c_data>
<c_barfilled text='Page views' alpha=50 color='#9933CC' outline='#8010A0' size=10></c_barfilled>
<c_xlabels data='January,February,March,April,May,June,July,August,September'></c_xlabels>
<c_xaxissteps data=2></c_xaxissteps>
<c_xlabelstyle size=10 color=#9933CC' orientation=0 step=2></c_xlabelstyle>
<c_ymax data=10></c_ymax>
<c_ylabelsteps data=4></c_ylabelsteps>
<c_ylegend text='Open Flash Chart' size=12 color='#736AFF'></c_ylegend>
</div>


- [ Charts ] - Bar Chart 2


사용자 삽입 이미지
 

<div class="charthtc" style="width:680px;height:200px">
<c_title text='Bar Chart' cstyle='{font-size: 20px; color: #736AFF}'></c_title>
<c_data data='3,3,2,2,3,3,4,2,3'></c_data>
<c_data data='6,6,6,7,6,8,8,8,9'></c_data>
<c_data data='4,3,3,2,7,6,3,9,8'></c_data>
<c_bar text='Me' alpha=50 color='#0066CC' size=10></c_bar>
<c_bar text='You' alpha=50 color='#9933CC' size=10></c_bar>
<c_bar text='Them' alpha=50 color='#639F45' size=10></c_bar>
<c_xlabels data='January,February,March,April,May,June,July,August,September'></c_xlabels>
<c_xlabelstyle size=10 color=#9933CC' orientation=0 step=2></c_xlabelstyle>
<c_xaxissteps data=2></c_xaxissteps>
<c_ymax data=10></c_ymax>
<c_ylabelsteps data=2></c_ylabelsteps>
<c_ylegend text='Open Flash Chart' size=12 color='#736AFF' ></c_ylegend>
</div>


- [ Charts ] - Bar Chart Glass


사용자 삽입 이미지
 
<div class="charthtc" style="width:680px;height:200px">
<c_title text='Glass Bars' cstyle='{font-size:20px; color: #bcd6ff; margin:10px;
background-color: #5E83BF; padding: 5px 15px 5px 15px;}'></c_title>
<c_data data='5,5,3,2,4,2,3,3,4,3'></c_data>
<c_data data='-5,7,-2,9,-1,8,-3,4,6,7'></c_data>
<c_barglass alpha='75' color='#D54C78' text='2006' size=10></c_barglass>
<c_barglass alpha='75' color='#3334AD' text='2007' size=10></c_barglass>
<c_xaxiscolour data='#909090' grid='#ADB5C7'></c_xaxiscolour>
<c_yaxiscolour data='#909090' grid='#ADB5C7'></c_yaxiscolour>
<c_xlabels data='January,February,March,April,May,June,July,August,September,October'></c_xlabels>
<c_ymin data=-5></c_ymin>
<c_ymax data=10></c_ymax>
<c_ylabelsteps data=6></c_ylabelsteps>
<c_ylegend text='Open Flash Chart' size=12 color='#736AFF' ></c_ylegend>
</div>


- [ Charts ] - Bar Chart 3D


사용자 삽입 이미지
 

<div class="charthtc" style="width:680px;height:200px">
<c_title text='3D Bar Chart' cstyle='{font-size:20px; color: #FFFFFF; margin: 5px;
    background-color: #505050; padding:5px; padding-left: 20px; padding-right: 20px;}'></c_title>
<c_data data='3,3,2,5,5,5,4,4,5,2'></c_data>
<c_data data='9,5,7,5,8,9,8,5,9,7'></c_data>
<c_xaxis3d data='12'></c_xaxis3d>
<c_bar3d alpha='75' color='#D54C78' text='2006' size=10></c_bar3d>
<c_bar3d alpha='75' color='#3334AD' text='2007' size=10></c_bar3d>
<c_xaxiscolour data='#909090' grid='#ADB5C7'></c_xaxiscolour>
<c_yaxiscolour data='#909090' grid='#ADB5C7'></c_yaxiscolour>
<c_xlabels data='January,February,March,April,May,June,July,August,September,October'></c_xlabels>
<c_ymax data=10></c_ymax>
<c_ylabelsteps data=5></c_ylabelsteps>
<c_ylegend text='Open Flash Chart' size=12 color='#736AFF' ></c_ylegend>
</div>



- [ Charts ] - Bar Chart Sketch


사용자 삽입 이미지
 
<div class="charthtc" style="width:680px;height:200px">
<c_title text='Bar Chart Sketch' cstyle='{font-size:20px; color: #FFFFFF; margin: 5px;
    background-color: #505050; padding:5px; padding-left: 20px; padding-right: 20px;}'></c_title>
<c_data data='4,3,2,3,5,4,4,4,2,5'></c_data>
<c_data data='7,5,9,5,7,9,5,9,9,9'></c_data>
<c_barsketch alpha='75' offset=6 color='#D54C78' text='2006' size=10></c_barsketch>
<c_barsketch alpha='75' offset=6 color='#3334AD' text='2007' size=10></c_barsketch>
<c_xaxiscolour data='#909090' grid='#ADB5C7'></c_xaxiscolour>
<c_yaxiscolour data='#909090' grid='#ADB5C7'></c_yaxiscolour>
<c_xlabels data='January,February,March,April,May,June,July,August,September,October'></c_xlabels>
<c_xlabelstyle size=10 color=#9933CC' orientation=2></c_xlabelstyle>
<c_ymax data=10></c_ymax>
<c_ylabelsteps data=5></c_ylabelsteps>
<c_ylegend text='Open Flash Chart' size=12 color='#736AFF' ></c_ylegend>
</div>




- [ Charts ] - Area
사용자 삽입 이미지
 

<div class="charthtc" style="width:680px;height:200px">
<c_title text='Area Chart' cstyle='{font-size:20px; color: #FFFFFF; margin: 5px;
    background-color: #505050; padding:5px; padding-left: 20px; padding-right: 20px;}'></c_title>
<c_data data='0,0.377471728511,0.739894850386,1.07282069945,1.36297657271,1.59879487114,1.77087426334,1.87235448698,1.89918984578,1.85031049867,1.72766511097,1.53614316726,1.28338004305,0.979452606461,0.636477485296,0.268128015314,-0.110910872512,-0.485528093851,-0.84078884226,-1.16252999279,-1.43792474109,-1.65599396759,-1.80804394039,-1.8880129069,-1.89271275679,-1.82195612186,-1.67856384587,-1.46825252636,-1.19940661196,-0.882744140886,-0.530889446578'></c_data>
<c_areahollow width=2 alpha=25 dotsize='3' color='#CC3399' text='2006' size=10 fillcolor=#773399></c_areahollow>
<c_xaxiscolour data='#909090' grid='#ADB5C7'></c_xaxiscolour>
<c_yaxiscolour data='#909090' grid='#ADB5C7'></c_yaxiscolour>
<c_xlabels data='0.00,0.38,0.74,1.07,1.36,1.60,1.77,1.87,1.90,1.85,1.73,1.54,1.28,0.98,0.64,0.27,-0.11,-0.49,-0.84,-1.16,-1.44,-1.66,-1.81,-1.89,-1.89,-1.82,-1.68,-1.47,-1.20,-0.88,-0.53'></c_xlabels>
<c_xlabelstyle size=10 color=#9933CC' orientation=2></c_xlabelstyle>
<c_ymin data=-2></c_ymin>
<c_ymax data=2></c_ymax>
<c_ylabelsteps data=5></c_ylabelsteps>
<c_ylegend text='Open Flash Chart' size=12 color='#736AFF' ></c_ylegend>
</div>


- [ Charts ] - Bar + Line Chart


사용자 삽입 이미지
 
<div class="charthtc" style="width:680px;height:200px">
<c_title text='Many data lines' cstyle='{font-size: 20px; color: #736AFF}'></c_title>
<c_data data='16,19,16,19,16,17,18,16,17,17'></c_data>
<c_data data='10,11,8,11,13,13,12,12,10,9'></c_data>
<c_data data='7,1,7,4,5,1,4,1,7,6'></c_data>
<c_bar text='Page views' color='#9933CC' size=10 width=2></c_bar>
<c_bar text='Downloads' color='#CC3399' size=10 width=3></c_bar>
<c_linedot text='Bounces' color='#80a033' size=10 width=2 dotsize=4></c_linedot>
<c_xlabels data='January,February,March,April,May,June,July,August,September,October'></c_xlabels>
<c_xlabelstyle size=10 color=#9933CC' orientation=2></c_xlabelstyle>
</div>


- [ Charts ] - Pie Chart


 
사용자 삽입 이미지

<div class="charthtc" style="width:300px;height:200px">
<c_pie alpha=60 color='#505050' gradient=true cstyle='{font-size: 12px; color: #404040;}' ></c_pie>
<c_pievalues data='10,12,7,9,10' text='IE,Firefox,Opera,Wii,Other'></c_pievalues>
<c_pieslicecolours data='#d01f3c,#356aa0,#C79810'></c_pieslicecolours>
<c_tooltip data='#val#%'></c_tooltip>
</div>

<div class="charthtc" style="width:300px;height:200px">
<c_pie alpha=60 color='#505050' gradient=false cstyle='{font-size: 12px; color: #404040;}' ></c_pie>
<c_pievalues data='10,12,7,9,10' text='IE,Firefox,Opera,Wii,Other'></c_pievalues>
<c_pieslicecolours data='#d01f3c,#356aa0,#C79810'></c_pieslicecolours>
<c_tooltip data='#val#%'></c_tooltip>
</div>


- [ Charts ] - Scatter Chart


 
사용자 삽입 이미지

<div class="charthtc" style="width:680px;height:200px">
<c_title text='Scatter Chart' cstyle='{font-size: 20px; color: #736AFF}'></c_title>
<c_value x='15' y='9' size='18'></c_value>
<c_value x='11' y='19' size='6'></c_value>
<c_value x='9' y='13' size='11'></c_value>
<c_value x='20' y='4' size='11'></c_value>
<c_value x='12' y='18' size='12'></c_value>
<c_value x='15' y='16' size='9'></c_value>
<c_value x='8' y='5' size='15'></c_value>
<c_value x='6' y='3' size='20'></c_value>
<c_value x='14' y='8' size='8'></c_value>
<c_value x='5' y='8' size='9'></c_value>
<c_value x='15' y='7' size='6'></c_value>
<c_value x='18' y='6' size='5'></c_value>
<c_value x='18' y='4' size='4'></c_value>
<c_value x='20' y='15' size='18'></c_value>
<c_value x='15' y='2' size='3'></c_value>
<c_scatter text='Downloads' color='#CC3399' size=10 width=2></c_scatter>
<c_value x='18' y='8' size='17'></c_value>
<c_value x='10' y='13' size='16'></c_value>
<c_value x='4' y='2' size='19'></c_value>
<c_value x='7' y='3' size='4'></c_value>
<c_value x='5' y='1' size='19'></c_value>
<c_value x='12' y='14' size='16'></c_value>
<c_value x='11' y='15' size='8'></c_value>
<c_value x='16' y='8' size='5'></c_value>
<c_value x='3' y='16' size='11'></c_value>
<c_value x='16' y='13' size='10'></c_value>
<c_value x='1' y='19' size='19'></c_value>
<c_value x='11' y='18' size='19'></c_value>
<c_value x='17' y='0' size='11'></c_value>
<c_value x='5' y='18' size='14'></c_value>
<c_value x='1' y='19' size='15'></c_value>
<c_scatter text='Uploads' color='#80a033' size=10 width=2></c_scatter>
<c_xmin data=0></c_xmin>
<c_xmax data=20></c_xmax>
<c_ymin data=0></c_ymin>
<c_ymax data=20></c_ymax>
<c_xlegend data='Open Flash Chart' color=#464646 size=16></c_xlegend>
</div>


아이프레임의 새로길이를 가져올 파일의 길이에 따라 자동으로 조절되도록 하기 위한 소스팁입니다...

여러가지 방법이 있지만 두가지 정도를 올려봅니다..

1. 프로그램으로 처리할 경우

스크립트 소스를 아래와 같이 넣어준 후 해당 iframe에 onload="iframe_autoresize(this)"를 넣어주세요...
===스크립트 처리===
<script>
function iframe_autoresize(arg) {
arg.height =
eval(arg.name+".document.body.scrollHeight");
}
</script>
===해당 iframe처리===
<iframe src="가져올 파일경로" onload="iframe_autoresize(this)">


2. 자바스크립트만으로 처리할 경우

<a href="파일링크" target="vision"> 첫번째파일</a>
<a href="파일링크" target="vision"> 두번째파일</a>
<iframe id="free_size" src="가져올 파일경로" width=10 height=10 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no name="vision"></iframe>

링크경로에 target="vision"을 꼭 넣어주시고,
해당위치에 iframe을 넣은 후 id값을 위와 같이 넣어줍니다. id명은 원하시는대로 바꾸시면 되구요.. 넓이와 높이값은 제조정되기에 그냥 10으로 넣었습니다... 그리고 가져오는 해당 파일의 내용을 아래와같이 <div>안에 넣어주시고 아래의 스크립트를 넣어주시면 됩니다....^^

<div align=center id="page_content" style="position:absolute;left:0;top:0;width:100%">
<table>
<tr><td>내용부분</td></tr>
</table>
</div>
<script language="JavaScript1.2">
function iframe_reset(){
dataobj=document.all? document.all.page_content : document.getElementById("page_content")

dataobj.style.top=0
dataobj.style.left=0

pagelength=dataobj.offsetHeight
pagewidth=dataobj.offsetWidth

parent.document.all.free_size.height=pagelength
parent.document.all.free_size.width=pagewidth
}
window.onload=iframe_reset
</script>

예전에 자바스크립트는 단순히 배경색을 바꾸거나 입력형식을 검사하는 등의 용도로 사용되었으나 지금은 DHTML과 결합하여 상당히 덩치가 커지게 되었다. 그래서 이제는 성능이라는 것을 고려해야 한다. 이번장에서는 자바스크립트의 성능을 향상시킬수 있는 일반적인 방법 3가지를 살펴보겠다.

개체들을 캐싱시켜라...

자바스크립트의 성능을 향상시킬수 있는 방법중 하나는 개체를 캐싱시키는 것이다. 다음과 같이 반복적인 작업을 수행하는 스크립트가 있다고 하자.
 

<script language="JavaScript1.1">
for (i=0;i<document.images.length;i++)
document.images[i].src="blank.gif"
</script>


위의 예에서 document.images라는 개체는 여러번 불리워지고 있다. 각각의 루프가 돌때마다 document.images가 두번씩 읽혀지고 있다. 우리가 불러들여야 되는 것은 images 뿐이다. 하지만 여기서는 document를 거쳐서 images에 도달하고 있다. 이를 조금 개선해보자.
 

<script language="JavaScript1.1">
var theimages=document.images
for (i=0;i<theimages.length;i++)
theimages[i].src="blank.gif"
</script>


이제 성능향상이 되었다는 것이 보일것이다. 개체를 캐싱시키라는 뜻은 반복적으로, 그리고 순차적으로 접근되어가는 개체를 사용자가 정의한 변수에 넣어서 사용하라는 것이다. 위의 예에서 document.images를 theimages라는 변수에 넣었다.그리고 루프에서 이를 사용함으로서 document -> images가 아닌 images만 액세스하게 되었다.

이와 같은 사용예는 document.all.someobject , document.layers.somelayer 등에 사용할 수 있다.

스크립트를 캐싱하라...

성능을 향상시키는 또 다른 방법은 스크립트를 통채로 캐싱시키는 것이다. 스크립트를 js파일에 저장하고 이를 사용하면 페이지 Reload나 두번째 방문시 이후는 캐시에서 이를 꺼내 사용하게 된다.
 

<script src="imagescript.js"></script>


이러한 스크립트 캐싱은 스크립트의 양이 많거나 여러 페이지에 삽입되어 사용할 경우 좋은 효과를 낼 수 있다.

상황에 맞는 개체를 사용하라... 

각각의 개체를 상황에 맞게 사용하여야 한다. 다음의 두 동적 속성을 보자.
 

-object.innerText
-object.innerHTML


첫번째보다 두번째 속성이 더 자원을 많이 사용하게 된다. <DIV>나 <SPAN> 안에 텍스트 문자들만 들어가게 한다면 innerText를 사용하여 좋은 성능효과를 볼 수 있을 것이다. 이와 같은 것으로 CSS의 Display와 Visibility가 있다. 역시 후자에 비해 전자가 자원소모가 더 많다.

마무리

많은 사람들이 자바스크립트가 C나 자바와 같은 덩치 큰 언어가 되는 것은 시간문제라고 생각하고 있다. 그렇다면 이제 성능에 대하여 한번쯤 다시 생각해보아야 할 때가 아닌가 생각한다.

+ Recent posts