레이블이 javascript인 게시물을 표시합니다. 모든 게시물 표시
레이블이 javascript인 게시물을 표시합니다. 모든 게시물 표시

javascript의 세상

1. 세미콜론이 필요없다. 그러나 세미콜론이 있어도 상관없다.
아주 가끔 세미콜론이 없어서 문제가 되는 일이 생긴다.




2. 함수의 이름을 노출시키는 함수정의 방법

  function f1(){
    alert('...')
  }

  f1();




3. 함수의 이름을 노출시키지 않는 함수정의 방법

이 방법을 통하면 정의된 함수를 실행시킬 방법이 없다. 그래서 정의함과 동시에 실행시킨다. 이름이 없으므로 실행은 이때 단 한번만 가능하다.

  (function (a) {
    alert(a);
  }) ('xyz');  // 세미콜론이 꼭 필요한 경우이다

  (function (a) {
    alert(a);
  } ('abc') );  // 세미콜론이 꼭 필요한 경우이다

이처럼 괄호 안에 함수가 정의되어 있으면 괄호 바깥에서는 그 함수의 존재사실을 알지 못한다. 이름을 노출시키지 않기위해 괄호안에 정의한 객체들은 결국은 javascript에서 private class의 역할을 한다.



위의 예에서 함수의 인자를 전달하는데 두가지 방법이 있음을 눈치챘다.




4. 함수인자의 전달 vs 함수이름의 전달

함수인자를 전달하거나
  (function ( arg ) {

    alert( arg );
  } ( 'abc' ) );

함수이름을 전달한다.
  (function ( fn ) {
    fn( 'abc' );
  } ( alert ) );

함수이름 (또는 함수의 포인터)를 전달할때는 괄호를 빼면 된다. 괄호가 포함되면 함수는 실행되어버린다. 위의 예에서는 alert함수의 포인터를 전달하기위해서 alert()에서 괄호를 뺀 alert만 사용했다.




5. 노출되지 않은 변수명을 외부로 노출시키는 방법


  (function() {
    var age = 20;
    var real_age = 30;
  } () );

위의 예에서, 외부에 age만 노출시키고싶으면 다음과 같이 한다.


  var global = {};  // 1. 이름이 노출되는 방식으로 선언된 객체 global

  (function( g ) {  // 3. global을 인자로 받고
    var age = 20;
    var real_age = 30;
    g.age = age;  // 4. 노출시키고싶은 변수를 global의 새 항목으로 등록한다
  } (global) );  // 2. global을 인자로 전달하고




6.











javascript 함수에서 불특정 갯수의 인자를 처리하는 방법


arguments 라는 객체가 있다.
arguments[0] 은 첫번째 인자이고, 인자의 갯수는 arguments.length이다.

인자를 출력하는 테스트를 해보자.

function aaa(n) {
  for( var i=0; i<arguments.length; i++ )
    console.log(n, '> ', arguments[i]);
}
aaa(2,9,8);

실행결과는 다음과 같다.
2> 2 ... 첫번째 인자는 n으로도 접근할 수 있고, arguments[0]으로도 접근할 수 있다.
2> 9
2> 8






arguments.callee라는 객체가 있다. 그것은 호출된 함수 그 자체이다. alert(arguments.callee); 라고 해보면 함수 전체가 출력되는것을 보게된다.
함수에게 전달되어야 할 인자의 갯수는 arguments.callee.length이다. Length가 이런 값을 리턴하는것은 조금 어처구니가 없다.






함수의 인자 갯수가 많아지면, 인자의 순서를 지켜서 입력하는것이 번거로울 수가 있다.
이럴때는 인자를 dictionary로 전달한다.

function tell_me_what_to_do( x ) {
  if( x.money == 'enough' ) {
if( x.weather == 'sunny' )
return 'have fun';
if( x.weather != 'sunny' )
 return 'have fun!';
  }
}

tell_me_what_to_do( { weather: 'sunny', money: 'enough' } );



named anchor사이를 오가되 history에 남기지 않는 방법

named anchor를 몇 군데 두고서 여기저기 오가다 이전 사이트로 되돌아가려고 back버튼을 누르면, 안타깝게도 다른 사이트가 아닌 바로 전에 봤던 named anchor로 되돌아간다. Back버튼을 수차례 눌러야만 비로소 이전의 사이트로 되돌아갈 수 있다.

분명 이것은 원하는 것이 아닐것이다.
해결하는 방법은 window.location.replace를 이용하는 것이다.




1. 여기 여러개의 named anchor가 있다.

  <a id='a1' class='named-anchor' href="#a1"> <img src="gif1.gif"> </a>
  <a id='a2' class='named-anchor' href="#a2"> <img src="gif2.gif"> </a>
  <a id='a3' class='named-anchor' href="#a3"> <img src="gif3.gif"> </a>




2. Javascript를 이용하여 named anchor가 클릭되면 history에 흔적을 남기지 않고 바로 이동시킨다.

  $(document).ready( function() {
    $('.named-anchor').click( function() {
      window.location.replace( $(this).attr('href') );
    });
  });





javascript로 cookie를 다루는 방법

이것은 auction 사이트에서 본 코드인데, 다른 사이트에서도 동일한 함수들이 보이는 것으로 봤을때 (1) 표준이거나 (2) 동일한 개발자가 만든 사이트들이다.

아무튼...


1. 아래와 같은 방법으로 쿠키를 쓴다.

function setCookie( name, value, expiredays ) {
  var endDate = new Date();
  endDate.setDate(endDate.getDate() + expiredays);
  document.cookie = name + "=" + escape( value ) +

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




2. 아래와 같은 방법으로 쿠키를 읽는다.

function getCookie( name ) {
  var nameOfCookie = name + "=";
  var x = 0;
  while ( x <= document.cookie.length ) {
    var y = (x+nameOfCookie.length);
    if ( document.cookie.substring( x, y ) == nameOfCookie ) {
      if ( (endOfCookie=document.cookie.indexOf( ";", y )) == -1 )
        endOfCookie = document.cookie.length;
      return unescape( document.cookie.substring( y, endOfCookie ) );
    }
    x = document.cookie.indexOf( " ", x ) + 1;
    if ( x == 0 )
      break;
  }
  return "";
}




3. 쿠키를 활용해서 팝업을 연다.
function openPopup( name ){
  if( getCookie( name ) != 'Y' )
    $('#popup').show();
}




4. 쿠키를 활용해서 팝업을 닫는다.

function closePopup() {
  setCookie("appBanner" , "Y" , 1);
  $('#popup').hide();
  return false;
}




javascript를 이용해서 화면 회전간에 화면의 특정 위치에 머물러있게 하는 방법

데스크톱 브라우저의 화면 너비가 변하거나, 휴대폰 브라우저의 화면이 회전하는 경우, 화면에 나타나는 부분은 내가 보고있던 내용과 무관한 경우가 허다하다.

이런 문제를 해결하려면 화면의 너비가 달라지더라도 직전에 보고있던 부분이 화면안에 나타나도록 처리를 해야 한다.




1. 화면의 가로 스크롤 위치를 저장하는 변수를 둔다.

  var sy;





2. scroll 이벤트가 발생할때마다 그 변수를 업데이트시킨다.

  $(window).scroll( function(){
    sy = $(window).scrollTop() / $(document).height();
  });




3. 화면의 너비가 변화시켜 레이아웃을 유발하는 이벤트가 발생하면, 그 변수를 활용해서 적절한 위치로 스크롤 시킨다.

  $(window).on('orientationchange resize', function(){
    $(window).scrollTop( $(document).height() * sy );
  });



javascript의 loop





    var rs = [10,20,30,40,50];
    var out = $('#out');

    for( var i=0; i<rs.length; i++ ) {
      // 무엇인가 한다

      if(rs[i] > 20) {
        break;  // 루프를 마친다
      }
    }







창의 크기변화에 따른 각종 width와 height의 변화 관찰

창의 너비를 변화시키는 실험을 해보자.



창의 너비가 충분한 경우 각 width의 변화를 살펴보면

    일정:
        없음

    변화:
        window,  html, document

    서로 같아요:
        window,  html, document

    상하 스크롤바가 나타나는 조건:
        window < document




창의 너비가 부족한 경우에는

    일정:
        document

    변화:
        window,  html

    서로 같아요:
        window,  html

    상하 스크롤바가 나타나는 조건:
        window > document







창의 높이를 변화시키는 실험을 해보자.



창의 높이가 충분한 경우 각 height의 변화를 살펴보면,

    일정:
        html,  body

    변화:
        window,  document

    서로 같아요:
        window,  document

    상하 스크롤바가 나타나는 조건:
        window < html




창의 높이가 부족한 경우에는

    일정:
        html,  body

    변화:
        window

    서로 같아요:
        html,  document

    상하 스크롤바가 사라지는 조건:
        window > html




javascript로 한 이미지의 url을 다른 것으로 바꿔치기

휴대폰을 위한 웹페이지를 만드는데, 배경에 사용될 그림의 크기가 1920 x 11400이고, 파일의 크기가 4MB나 된다.
이 비대한 배경이미지때문에 넓은 부분이 하얗게 남아있고, 레이아웃중인 어정쩡한 상태의 화면이 장시간동안 나타나며, 그 시간동안 사용자의 조작에 응답하지 못한다.

해결방법은 배경이미지의 크기를 아주 작게 만들어서, 큰 배경이미지가 주는 부담을 제거하는 것이다.

그래서, 처음에는 50x297 크기의 배경이미지를 사용하고, 나중에 더 높은 해상도의 배경이미지로 교체하는 방법으로 이 문제를 해결했다.

이 방법을 적용하고나니 처음에는 생각하지 않았던 좋은 점이 생겼는데, 화면이 작은 휴대폰에는 너무 큰 이미지를 사용하지 않아도 된다는 것이다. 화면 크기가 480 x 800인 휴대폰에 1920 x 11400 크기의 이미지가 무슨 소용인가? 더군다나 사용자가 zoom도 하지 못하게 차단시킨 상태인데.



바꿔치기하는 방법은 다음과 같다.


1. img 태그를 둔다. 처음에는 width=50px인 이미지를 표시한다. 웹페이지가 열리면서 이 작은 이미지가 재빠르게 로드되고, 이미지는 확대되어 화면 가득 표시된다. 굉장히 저화질의 화면을 얻게 된다.

  <img id="bg" src="poo-50.jpg" />

poo-50.jpg는 너비가 50픽셀이고,
poo-150.jpg는 너비가 150픽셀이고,
poo-1920.jpg는 너비가 1920픽셀이다.




2. 이 이미지의 로딩이 완료되면 load이벤트가 발생하는데, 이때 해상도가 더 높은 이미지로 교체한다. 그런데 이미지가 캐쉬되어있으면 load이벤트가 없다고 한다. 그래서, 이미 로딩이 완료되었는지를 확인하여 로딩완료된 경우라면 load() 이벤트 핸들러를 호출해준다.

  $(document).ready( function(){
    $('#bg').on('load', higher_resolution).
         each( function() {
           if( this.complete ) $(this).load();
         });
    ...
  });




3. higher_resolution() 이라는 함수는 다음과 같다.

  var res = 50;

  function higher_resolution() {

    switch( res ) {

      case   50:
        res=150;
        setTimeout('$("#bg").attr("src", "poo-150.jpg")', 500);
        break;

      case  150:
        res=1920;
        setTimeout('$("#bg").attr("src", "poo-1920.jpg")', 500);
        break;

      case 1920:
        break;
    }
  }




4. poo-50.jpg가 로드되어 화면에 나타난 후 500ms를 기다렸다가 poo-150.jpg를 로딩하기 시작한다. 이 500ms라는 시간동안 브라우저는 레이아웃 등의 작업을 하게 된다. poo-150.jpg가 로드되어 화면에 나타나면 500ms후에 poo-1920.jpg를 로딩하기 시작한다.




5. 아래와 같이 조건문을 하나 삽입하면, 휴대폰 화면 크기보다 큰 이미지를 불필요하게 로딩하는 경우를 피할 수 있다.

  var res = 50;
  function higher_resolution() {
    switch( res ) {
      case   50:
        if($(window).width() > res)
          res=150,
          setTimeout('$("#bg").attr("src", "poo-150.jpg")', 500);
        break;
      case  150:
        if($(window).width() > res)
          res=1920,
          setTimeout('$("#bg").attr("src", "poo-1920.jpg")', 500);
        break;
      case 1920:
        break;
    }
  }





6. 위의 예들은 최저해상도의 이미지에서 조금씩 높은 해상도의 이미지로 점진적으로 바꿔치기하고 있다.
최저해상도 이미지에서 최적의 해상도 이미지로 단 1회 바꿔치기를 하려면 다음과 같이 한다. 뿌옇게 답답한 화면이 좀 오래 지속되는 반면에 트래픽을 더 많이 감소시킬 수 있다.

  function higher_resolution() {
    var ww = $(window).width();
    var rs = [50, 150, 800, 1300, 1920];
    if( ww > res ) {
      for( var i=0; i<rs.length; i++ ) {
        if( ww <= rs[i] ) break;
      }
      if( rs.length == i ) {
        res = 999999999;
        src = "poo-" + rs[ rs.length-1 ] + ".jpg";
      }
      else {
        res = rs[i];
        src = "poo-" + rs[i] + ".jpg";
      }
      setTimeout('$("#bg").attr("src", "' + src + '")', 1000);
    }
  }





7. 화면 폭의 변화는 휴대폰이 회전되었을때도 일어난다. 그래서 다음과 같은 코드도 필요하다.

  $(document).ready( function(){
    ...
    $(window).on('orientationchange resize', function(){
      higher_resolution();
    });
    ...
  )};

javascript로 이미지를 다른 이미지 밑으로 드래그하여 이동시키는 방법

두 이미지가 중첩되면 drag중인 이미지의 drop이 방해받는다.
mouse up 이벤트 핸들러를 <html>에 등록시키면 이 문제를 해결할 수 있다.


<!DOCTYPE html>
<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script>
    $(function() {
      var debug = $('#debug');
      var o = $('#my_ball');
      var sx, sy, dx, dy, ix, iy;
      var dragging = false;
      $('#my_ball').on('mousedown', function(e) {
        e.preventDefault();
        sx = e.pageX;
        sy = e.pageY;
        ix = $(o).offset().left;
        iy = $(o).offset().top;
        dx=dy=0;
        dragging = true;
        console.log("mousedown - s:",sx,sy,"/i:",ix,iy);
      });
      $('html').on('mousemove', function(e) {
        if(dragging) {
          dx = e.pageX - sx;
          dy = e.pageY - sy;
          $(o).offset({left: ix+dx, top: iy+dy});
          $(debug).text(dx + "," + dy);
        }
      }).on('mouseup', function(e){
        if(dragging) {
dx = e.pageX - sx; dy = e.pageY - sy; $(o).offset({left: ix+dx, top: iy+dy}); dragging = false; console.log("mouseup - d:",dx,dy,"/i:",ix,iy);
        }
}); }); </script> </head> <body> <img src="ball.png" style="position:relative;" id="my_ball"> <img src="ball2.png" style="position:relative;"> <p style="text-align:right;" id="debug"> </p> </body> </html>

javascript를 이용해서 그림을 마우스로 끌어서 옮기는 방법

마우스로 그림을 끌어 옮기는 것은 다음 세가지 이벤트가 순서대로 일어나는 것이다.

mouse down --> mouse move --> mouse up



Mouse down에서는
  • drag가 시작되었다고 표시하고
  • 마우스가 클릭된 위치를 기억하고 (sx, sy)
  • 마우스가 드래그된 거리를 초기화시키고 (dx, dy)
  • 당시의 그림의 위치를 기억한다. (ix, iy)

Mouse move에서는
  • dx와 dy를 계산하고,
  • 그림의 첫 위치인 (ix, iy)에 (dx, dy)만큼 이동시킨 위치로 그림을 이동시킨다

Mouse up에서는
  • drag가 종료되었다고 표시하고
  • dx와 dy를 최종적으로 계산하고
  • 그림의 첫 위치인 (ix, iy)에 (dx, dy)만큼 이동시킨 위치로 그림을 이동시킨다



<!DOCTYPE html>
<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script>
    $(function() {
      var debug = $('#debug');
      var o = $('#my_ball');
      var sx, sy, dx, dy, ix, iy;
      var dragging = false;
      $('#my_ball').on('mousedown', function(e) {
        e.preventDefault();
        sx = e.pageX;
        sy = e.pageY;
        ix = $(o).offset().left;
        iy = $(o).offset().top;
        dx=dy=0;
        dragging = true;
        console.log("mousedown - s:",sx,sy,"/i:",ix,iy);
      }).on('mousemove', function(e) {
        if(dragging) {
          dx = e.pageX - sx;
          dy = e.pageY - sy;
          $(o).offset({left: ix + dx, top: iy + dy});
          $(debug).text(dx + "," + dy);
        }
      }).on('mouseup', function(e){
        dx = e.pageX - sx;
        dy = e.pageY - sy;
        $(o).offset({left: ix + dx, top: iy + dy});
        dragging = false;
        console.log("mouseup - d:",dx,dy,"/i:",ix,iy);
      });
    });
    </script>
  </head>
  <body>
    <img id="my_ball" src="ball.png" style="position:absolute">
    <h1 style="text-align:right;" id="debug"> </h2>
  </body>
</html>




잘 동작한다. 그런데 빠른 속도로 그림을 끌면 그림을 놓치게 된다.
빠른 속도로 그림을 끌때는 마우스가 <img>를 벗어나서 <html> 영역에 들어가 있기때문에, 이것을 개선시키려면 <html>에 mousemove 이벤트 핸들러를 등록시켜야 한다.

javascript로 객체의 좌표를 다루는 방법

절대좌표는 브라우저의 화면이 기준이고, offset()함수를 이용해서 좌표를 알아내거나 설정할 수 있다.
상대좌표는 엘리먼트의 부모영역이 기준이고, position()함수를 이용해서 좌표를 알아내기만 할 수 있다.

    <!DOCTYPE html>
    <html>
      <head>
      <style>
        #pink { 
          background-color: pink; 
          position:absolute; 
          top: 34px; 
          left: 56px; 
          width:100px; 
          height:100px; 
          }
        #blue {
          background-color: blue; 
          position:relative;
          top: 5px; 
          left: 9px; 
          width:10px; 
          height:10px; 
          }
      </style>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
      </head>
      <body>
        <div id="pink">
          <div id="blue"></div>
        </div>
        <script>
          var p = $('#pink'), 
                b = $('#blue'),
              px, py, bx, by;

          px = p.offset().left;
          py = p.offset().top;
          alert('1p (' + px + ', ' + py + ')');
          
          bx = b.position().left;
          by = b.position().top;
          alert('1b (' + bx + ', ' + by + ')');

          p.offset({top:50, left:150});
          px = p.offset().left;
          py = p.offset().top;
          alert('2p (' + px + ', ' + py + ')');

          bx = b.position().left;
          by = b.position().top;
          alert('2b (' + bx + ', ' + by + ')');
        </script>
      </body>
    </html>

javascript로 마우스 클릭 위치 알아오기

마우스 클릭 이벤트가 발생하면 이벤트 핸들러를 통해서 발생한 그 이벤트를 받아볼수 있다.


    <!DOCTYPE html>
    <html id="area">
      <head>
      <style>
        #area { background-color: pink; }
      </style>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
      <script>
        $(function(){
          $('#area').click( function (event) {
            x = event.pageX; 
            y = event.pageY; 
            console.log(x, y);
          });
        });
      </script>
      </head>
    </html>


template안에 포함되어있는 javascript를 실행시키는 방법

참조: http://stackoverflow.com/questions/14261232/including-script-tag-in-script-type-text-template-tag



1. template를 만드는 tag의 파라미터로 javascript의 이름들을 적어준다.






2. template로 만든 항목이 화면에 표시된 후에 파라미터로 지정되어있는 javascript들을 하나씩 document의 head에 삽입시킨다.





3. 위의 예는 template로 만든 항목 하나에만 적용된다. 만들어진 모든 항목에 대해서 javascript를 실행시키려면 수정이 필요하다.

JavaScript Object의 속성과 매서드 확장하기

JavaScript Object의 속성과 매서드 확장하기

자바스크립트 에러를 보여주는 스크립트

http://oybso.tistory.com/entry/자바스크립트-에러를-잡는-스크립트

window.onerror = ErrorSetting
var e_msg="";
var e_file="";
var e_line="";

function ErrorSetting(msg, file_loc, line_no) {
     e_msg=msg;
     e_file=file_loc;
     e_line=line_no;
     return true;
}

어떻게 쓰는 거야?