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

2018년 11월 12일 월요일

javascript closure

closure 는 함수를 리턴하는 함수로 고립된 scope 영역을 만들어 dynamic scope 로 인한 고민을 덜어 줄 수 있다.

예)

function genClosure(i) {
    return function () { 
        i++;
        return i;
    }
}


var closure1 = genClosure(0);
console.log(closure1()); // 1
console.log(closure1()); // 2
console.log(closure1()); // 3

var closure2 = genClosure(100);
console.log(closure2()); // 101
console.log(closure2()); // 102
console.log(closure2()); // 103

console.log(closure1()); // 4

var i = 10;
var closure3 = genClosure(i);
console.log(closure3()); // 11
console.log(closure3()); // 12

console.log(i); // 10

2012년 6월 8일 금요일

Javascript animation

참고: http://www.w3schools.com/js/js_timing.asp

Animation 은 일정한 시간 간격으로 객체의 속성 등을 서서히 변화시키는 일이다.

일정한 시간 간격으로 원하는 작업을 하기 위해 setTimeout 함수를 이용한다.
setTimeout(function, delay);

예) 1초 마다 i 변수에 1을 더하고 표시한다.
<div id="value"></div>
<script type="text/javascript">
var i = 0;
var func = function() {
 i++;
 document.getElementById("value");
 setTimeout(func, 1000);
}
setTimeout(func, 1000);
</script>

Animation 객체
<script type="text/javascript">
function myanim(actionFunc, interval) {
 this.timer;
 this.interval = (interval != null) ? interval : 1000;
 this.actionFunc = actionFunc;
}
myanim.prototype.start = function() {
 this.stop();
 var me = this;
 if (this.actionFunc) {
  this.loop = function() {me.actionFunc();setTimeout(me.loop, me.interval);}
  this.loop();
 }
}
myanim.prototype.stop = function() {
 if (this.timer) clearTimeout(this.timer);
}
</script>

Animation 객체 사용하기
<div id="value2"></div>
<script type="text/javascript">
var j = 0;
var anim = new myanim(function(){j++;document.getElementById("value2").innerHTML=j;}, 1000);
</script>


Element 이동
div 객체의 위치 속성 값을 바꾼다.
1. div 준비
<div id="box1" style="position:absolute;width:100px;height:100px;border:solid 1px black"></div>

2. animation
<script type="text/javascript">
var x = 0;
var anim = new myanim(function(){
 x=(x+1)%100;
 document.getElementById("box1").style.left=x + "px";
}, 50);
</script>


2012년 3월 14일 수요일

[Javascript] Hex to Decimal and Decimal to Hex

Javascript 로 Hex 를 Decimal 로 변환/Decimal 을 Hex 로 변환
참고: http://javascript.about.com/library/blh2d.htm
function d2h(d) {
 return d.toString(16);
}
function h2d(h) {
 return parseInt(h,16);
}
toString() 함수는 Number 클래스에 존재하는 함수다. 아래가 더 정확하다.
function d2h(d) {
 return Number(d).toString(16);
}
padding 을 주고 싶을 수도 있다.
참고: http://www.electrictoolbox.com/pad-number-zeroes-javascript/
function pad(number, length) {
 var str = '' + number;
 while (str.length < length) {
  str = '0' + str;
 }
 return str;
}
예)
document.writeln(pad(d2h(10), 2));
결과:

2012년 3월 7일 수요일

Javascript Tetris


자바스크립트로 테트리스를 만들어 보았다.

Javascript Tetris

← : left, → : right, ↑ : rotate, ↓ down, space: drop
Level:Score:


Javascript code - expand
<script type="text/javascript">
      var VK_LEFT = 37;
      var VK_RIGHT = 39;
      var VK_DOWN = 40;
      var VK_UP = 38;
      var VK_SPACE = 32;
      function get(obj) {
   return (typeof obj == "string") ? document.getElementById(obj) : obj;
      }
      function Tetris(eltId, levelElt, scoreElt, gameoverElt, nextElt) {
   this.init(eltId, levelElt, scoreElt, gameoverElt, nextElt);
      }
      Tetris.prototype.init = function(eltId, levelElt, scoreElt, gameoverElt, nextElt) {

   // map size
   this.MAP_WIDTH = 12;
   this.MAP_HEIGHT = 20;

   // current block
   this.curTet = 0;
   this.curRot = 0;
   this.curPos = {x:0, y:0};

   // tet
   this.tet = new Array(7);
   this.tet[0] = new Array(2);
   this.tet[0][0] = new Array({x:0,y:0},{x:1,y:0},{x:2,y:0},{x:3,y:0});
   this.tet[0][1] = new Array({x:0,y:0},{x:0,y:1},{x:0,y:2},{x:0,y:3});
   this.tet[1] = new Array(2);
   this.tet[1][0] = new Array({x:0,y:0},{x:1,y:0},{x:1,y:1},{x:2,y:1});
   this.tet[1][1] = new Array({x:1,y:0},{x:1,y:1},{x:0,y:1},{x:0,y:2});
   this.tet[2] = new Array(2);
   this.tet[2][0] = new Array({x:0,y:1},{x:1,y:1},{x:1,y:0},{x:2,y:0});
   this.tet[2][1] = new Array({x:0,y:0},{x:0,y:1},{x:1,y:1},{x:1,y:2});
   this.tet[3] = new Array(4);
   this.tet[3][2] = new Array({x:0,y:0},{x:1,y:0},{x:2,y:0},{x:2,y:1});
   this.tet[3][3] = new Array({x:1,y:0},{x:1,y:1},{x:1,y:2},{x:0,y:2});
   this.tet[3][0] = new Array({x:0,y:0},{x:0,y:1},{x:1,y:1},{x:2,y:1});
   this.tet[3][1] = new Array({x:1,y:0},{x:0,y:0},{x:0,y:1},{x:0,y:2});
   this.tet[4] = new Array(4);
   this.tet[4][2] = new Array({x:0,y:0},{x:1,y:0},{x:2,y:0},{x:0,y:1});
   this.tet[4][3] = new Array({x:1,y:0},{x:1,y:1},{x:1,y:2},{x:0,y:0});
   this.tet[4][0] = new Array({x:2,y:0},{x:0,y:1},{x:1,y:1},{x:2,y:1});
   this.tet[4][1] = new Array({x:1,y:2},{x:0,y:0},{x:0,y:1},{x:0,y:2});
   this.tet[5] = new Array(4);
   this.tet[5][0] = new Array({x:0,y:1},{x:1,y:1},{x:2,y:1},{x:1,y:0});
   this.tet[5][1] = new Array({x:0,y:0},{x:0,y:1},{x:0,y:2},{x:1,y:1});
   this.tet[5][2] = new Array({x:0,y:0},{x:1,y:0},{x:2,y:0},{x:1,y:1});
   this.tet[5][3] = new Array({x:1,y:0},{x:1,y:1},{x:1,y:2},{x:0,y:1});
   this.tet[6] = new Array(1);
   this.tet[6][0] = new Array({x:0,y:0},{x:1,y:0},{x:0,y:1},{x:1,y:1});

   // map
   this.map = new Array(this.MAP_HEIGHT);
   for (var i = 0,limit = this.map.length; i < limit; i++) {
       this.map[i] = new Array(this.MAP_WIDTH);
       for (var x = 0, xlimit = this.map[i].length; x < xlimit; x++) {
    this.map[i][x] = 0;
       }
   }
   this.empty_line = new Array(this.MAP_WIDTH);
   for (var x = 0, xlimit = this.MAP_WIDTH; x < xlimit; x++) {this.empty_line[x] = 0;}

   // screen
   this.elt = get(eltId);
   this.inspire(this.elt);

   // level
   this.level_map = new Array(1000, 900, 800, 700, 600, 500, 400, 300, 200, 100);

   this.level = 0;
   this.levelElt = get(levelElt);

   // score
   this.score = 0;
   this.scoreElt = get(scoreElt);

   // game over
   this.gameoverElt = get(gameoverElt);

   // next
   this.next = null;
   this.nextElt = get(nextElt);
   this.inspireNext(this.nextElt);

   // status
   this.state = "ready";
      }
      Tetris.prototype.inspire = function (elt) {
   this.elt = elt;
   this.elt.innerHTML = "";
   for (var y = 0, ylimit = this.map.length; y < ylimit; y++) {
       this.elt.innerHTML += "<div class='line'>";
       for (var x = 0, xlimit = this.map[y].length; x < xlimit; x++) {
    this.elt.innerHTML += "<span id='" + (x + "_" + y)  + "' class='block'>0</span>";
       }
       this.elt.innerHTML += "</div>";
   }
      }
      Tetris.prototype.inspireNext = function(nextElt) {
   this.nextElt = nextElt;
   this.nextElt.innerHTML = "";
   for (var y = 0; y < 4; y++) {
       this.nextElt.innerHTML += "<div class='line'>";
       for (var x = 0; x < 4; x++) {
    this.nextElt.innerHTML += "<span id='next" + (x + "_" + y) + "' class='block'>0</span>";
       }
       this.nextElt.innerHTML += "</div>";
   }
      }
      Tetris.prototype.getMapBlock = function(x, y) {
   return this.map[y][x];
      }
      Tetris.prototype.setMapBlock = function(x, y, type) {
   this.map[y][x] = type;
      }
      Tetris.prototype.clearMap = function() {
   // clear map
   for (var y = 0; y < this.MAP_HEIGHT; y++) {
       for (var x = 0; x < this.MAP_WIDTH; x++) {
    this.setMapBlock(x, y, 0);
       }
   }
      }
      Tetris.prototype.gen = function() {
   this.curPos = {x:(this.MAP_WIDTH / 2) - 2,y:0};
   this.curRot = 0;
   if (this.next == null) {
       this.next = Math.floor(Math.random() * 10) % 7;
   }
   this.curTet = this.next;
   var n = Math.floor(Math.random() * 10) % 7;
   this.next = (n == this.curTet) ? ((n + (Math.floor(Math.random() * 10) % 6) + 1) % 7) : n;
   this.dropDelay(1000);

   if (this.checkCollid(this.curPos, this.curTet, this.curRot)) {
       this.gameOver();
   }
      }
      Tetris.prototype.sideWalk = function(offset) {
   var nextPos = {x:(this.curPos.x + offset), y:this.curPos.y};
   if (!this.checkCollid(nextPos, this.curTet, this.curRot))
       this.curPos = nextPos;
      }
      Tetris.prototype.down = function() {
   var nextPos = {x:this.curPos.x, y:(this.curPos.y + 1)};
   if (!this.checkCollid(nextPos, this.curTet, this.curRot)) {
       this.curPos = nextPos;
       this.dropDelay(this.level_map[this.level]);
       return true;
   } else {
       this.addToMap();
       this.removeFull();
       this.gen();
       return false;
   }
      }
      Tetris.prototype.rotate = function(offset) {
   var cnt = this.tet[this.curTet].length;
   var nextRot = (this.curRot + offset) % cnt;
   if (!this.checkCollid(this.curPos, this.curTet, nextRot))
       this.curRot = nextRot;
      }
      Tetris.prototype.checkCollid = function(pos, type, rot) {
   var b = this.tet[type][rot];
   for (var i = 0, limit = b.length; i < limit; i++) {
       var x = pos.x + b[i].x;
       var y = pos.y + b[i].y;
       if (x < 0 || x >= this.MAP_WIDTH) {
    return true;
       } else  if (y < 0 || y >= this.MAP_HEIGHT) {
    return true;
       } else if (this.getMapBlock(x, y) != 0) {
    return true;
       }
   }
   return false;
      }
      Tetris.prototype.addToMap = function() {
   var elt = this.tet[this.curTet][this.curRot];
   for (var i = 0, limit = elt.length; i < limit; i++) {
       this.setMapBlock(this.curPos.x + elt[i].x, this.curPos.y + elt[i].y, this.curTet + 1);
   }
      }
      Tetris.prototype.removeFull = function() {
   for (var y = this.MAP_HEIGHT - 1; y >= 0; y--) {
       var cnt = 0;
       for (var x = 0; x < this.MAP_WIDTH; x++) {
    if (this.getMapBlock(x, y) == 0)
        break;
    
    cnt++;
       }
       if (cnt == this.MAP_WIDTH) {
    for (var cy = y; cy > 0; cy--) {
        this.map[cy] = this.map[cy-1].slice();
    }
    this.map[0] = this.empty_line.slice();
    this.score += 25;
    this.level = Math.min(Math.floor((this.score / 250)), this.level_map.length - 1);
    y++;
       }
   }
      }
      Tetris.prototype.dropTimer = null;
      Tetris.prototype.drop = function(interval) {

   if (this.state == "start") {
       var ret = this.down();
       this.update();

       if (ret) {
    var me = this;
    clearTimeout(this.dropTimer);
    this.dropTimer = setTimeout(function() {me.drop(interval);}, interval);
       }
   }
      }
      Tetris.prototype.dropDelay = function(interval) {
   var me = this;
   clearTimeout(this.dropTimer);
   this.dropTimer = setTimeout(function() {me.drop(me.level_map[me.level]);}, interval);
      }
      Tetris.prototype.start = function() {

   this.clearMap();
   this.inspire(this.elt);
   this.inspireNext(this.nextElt);
   this.score = 0;
   this.level = 0;
   this.gen();

   this.state = "start";
   this.gameoverElt.innerHTML = "";
   this.update();

   var me = this;
   document.onkeydown = function(e) {me.handleInput(e);}
      }
      Tetris.prototype.gameOver = function() {

   // gray map
   for (var y = 0; y < this.MAP_HEIGHT; y++) {
       for (var x = 0; x < this.MAP_WIDTH; x++) {
    if (this.getMapBlock(x, y) != 0) {
        this.setMapBlock(x, y, 8);
    }
       }
   }
   
   clearTimeout(this.dropTimer);
   document.onkeydown = null;
   this.state = "gameover";
   this.update();
      }
      Tetris.prototype.stop = function() {
   this.clearMap();
   for (var y = 0; y < 4; y++) {
       for (var x = 0; x < 4; x++) {
    get("next" + (x + "_" + y)).className = "block";
       }
   }
   this.next = null;
   clearTimeout(this.dropTimer);
   this.score = 0;
   this.state = "stop";
   document.onkeydown = null;
   this.gameoverElt.innerHTML = "";
   this.update();
      }
      Tetris.prototype.preventDefault = function(e) {
   (e.preventDefault) ? e.preventDefault() : e.returnValue = false;
      }
      Tetris.prototype.handleInput = function(e) {
   var ev = (window.event) ? window.event : e;
   var keycode = (window.event) ? window.event.keyCode : e.which;
   switch (keycode) {
   case VK_LEFT:
       this.sideWalk(-1);
       this.preventDefault(ev);
       break;
   case VK_RIGHT:
       this.sideWalk(1);
       this.preventDefault(ev);
       break;
   case VK_UP:
       this.rotate(1);
       this.preventDefault(ev);
       break;
   case VK_DOWN:
       this.down();
       this.preventDefault(ev);
       break;
   case VK_SPACE:
       while (this.down()){}
       this.preventDefault(ev);
       break;
   default:
       break;
   }
   this.update();
      }
      Tetris.prototype.render = function() {
   for (var y = 0, ylimit = this.map.length; y < ylimit; y++) {
       for (var x = 0, xlimit = this.map[y].length; x < xlimit; x++) {
    var type = this.getMapBlock(x, y);
    get(x + "_" + y).innerHTML = "0";
    get(x + "_" + y).className = "block col" + type;
       }
   }

   if (this.state == "start") {
       this.drawTet(this.curPos, this.curTet, this.curRot);
   } else if (this.state == "gameover") {
       this.gameoverElt.innerHTML = "Game Over!!";
   }
   this.scoreElt.innerHTML = this.score;
   this.levelElt.innerHTML = this.level + 1;
   if (this.next != null)
       this.drawNext(this.next);
      }
      Tetris.prototype.drawBlock = function(x, y, type) {
   get(x + "_" + y).className = "block col" + type;
      }
      Tetris.prototype.drawTet = function(pos, type, rot) {
   var t = this.tet[type][rot];
   for (var i = 0, limit = t.length; i < limit; i++) {
       this.drawBlock(pos.x + t[i].x, pos.y + t[i].y, type + 1);
   }
      }
      Tetris.prototype.drawNext = function(type) {
   for (var y = 0; y < 4; y++) {
       for (var x = 0; x < 4; x++) {
    get("next" + (x + "_" + y)).className = "block";
       }
   }
   var t = this.tet[type][0];
   for (var i = 0, limit = t.length; i < limit; i++) {
       var n = get("next" + (t[i].x + "_" + t[i].y));
       n.innerHTML = "0";
       n.className = "block col" + (type + 1);
   }
      }
      Tetris.prototype.update = function() {
   this.render();
      }
</script>

2012년 3월 3일 토요일

Javascript keycode 확인

Javascript keycode 확인
아래 입력창을 클릭하고 키를 입력하면 키코드가 출력된다.

<script>
function keycodecheck(event) {
    var keycode = (window.event) ? window.event.keyCode : e.which;
}
</script>

2012년 2월 29일 수요일

Javascript 새창 띄우고 내용 넣기

참고: http://www.w3schools.com/jsref/met_win_open.asp

반드시 새로운 window.open() 함수 호출 시 url 을 넣을 필요는 없다.
url 에 빈 문자열 "" 을 넣어주면 빈 윈도우가 뜬다.
window.open() 함수는 윈도 객체를 리턴한다.
해당 윈도 객체에 write() 함수를 이용하여 내용을 채울 수 있다.

코드:
<script type="text/javascript">
var wnd = window.open("", "new window", "width=200,height=100");
wnd.document.write("<html><head><title>New Window Title!</title></head><body><h1 style='font-size:12pt;padding:5px;border:1px solid black;'>Hello</h1></body></html>");
</script>

테스트:

2012년 2월 28일 화요일

Ajax 사용

참고(ajax): http://www.w3schools.com/ajax/ajax_xmlhttprequest_create.asp
참고(convert html special character): http://stackoverflow.com/questions/784586/convert-special-characters-to-html-in-javascript

코드:
<script type="text/javascript">
function getXmlHttp() {
 var xmlhttp;
  
 if (window.XMLHttpRequest) {
  // code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
 } else {
  // code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
 }
 
 return xmlhttp;
}

function ajaxQuery(method, query, cb_onsuccess) {
 var xmlhttp = getXmlHttp();
 xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
   cb_onsuccess(xmlhttp);
  }
 }
 xmlhttp.open(method, query, true);
 xmlhttp.send();
}
</script>
팁) html 특수 문자 변환
<script type="text/javascript">
function htmlspecialchars(str) {
 return str.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
}
</script>
주의 사항: url 을 외부 사이트로 할 경우 외부 사이트에서 허용을 해야만 접근 가능


테스트: ajaxQuery('GET', '/', function(xmlhttp){document.getElementById('ajax-result').innerHTML = htmlspecialchars(xmlhttp.responseText);});

결과:

Javascript prototype 에서 this 의 scope 문제

prototype 에서 this 사용시 scope 에 유의해야 한다.

예) x 라는 객체가 있고 doSomething() 함수를 부르면 1초 후에 x 의 hello() 함수를 부른다.

function x() {}

x.prototype.hello = function() {
    alert("Hello");
}

x.prototype.doSomething = function() {
    setTimeout(function() {this.hello();}, 1000); // this 를 쓰면 안된다.
}


디버깅 툴을 열고 아래 버튼을 눌렀을 때 hell() 함수를 찾을 수 없다는 에러를 확인한다.


다음과 같이 고쳐 쓴다.

var me = this;
setTimeout(function() {me.hello();}, 1000);

아래는 성공한다.

2012년 2월 15일 수요일

Email Regex

참고: http://www.regular-expressions.info/email.html


Result:

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$
<script type="text/javascript">
function check(email) {
    var pattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
    return pattern.test(email);
}
</script>

2012년 2월 14일 화요일

[Javascript] Window 크기 및 스크롤 이벤트

스크롤 이벤트
window.onscroll 에 이벤트 처리 함수를 넣는다.
윈도우 크기 변화 이벤트
window.onresize 에 이벤트 처리 함수를 넣는다.




Javascript
<script type="text/javascript">
function get(obj) {
  if (typeof obj == "object") {
    return obj;
  }
  return document.getElementById(obj);
}
function setText(obj, text) {
  get(obj).innerHTML = text;
}
function appendText(obj, text) {
  get(obj).innerHTML += text;
}

window.onscroll = function() {
  setText("scroll-pos", "onscroll/top:" + document.body.scrollTop + ", left:" + document.body.scrollLeft);
};
window.onresize = function() {
  setText("window-size", "onresize/width:" + window.innerWidth + ", height:" + window.innerHeight);
};
</script>
CSS
<style type="text/css">
#status-box {z-index:50;position:fixed;background-color:white;bottom:10px;right:10px;border:2px solid black;padding:5px;}
</style>
HTML
<div id="status-box">
  <div id="scroll-pos"></div>
  <div id="window-size"></div>
</div>

2012년 2월 9일 목요일

Javascript Window 정보

Javascript Window 정보

2011년 6월 10일 금요일

Javascript session

웹 브라우저로 다른 페이지에 접속을 해도 이전 페이지에서 저장한 값들에 접근할 수 있는 방법 중에 하나가 session 을 사용하는 방법이다.

하지만 javascript 는 서버측 session 을 조작하거나 javascript 에서만 사용할 수 있는 session API 는 존재하지 않는다.

예를 들어 인터넷 라디오 웹 사이트를 제작한다고 했을 때 채널 리스트 페이지에서 채널을 선택하면 플레이어 페이지로 이동한다고 가정하자.
플레이어 화면에서 이전 페이지로 넘어가면 마지막 선택한 항목이 하이라이트되어 있어야 한다.
만약 웹 브라우저에서 이전 페이지로 이동시 마지막 상태를 복원해 준다면 다행이겠지만 그렇지 않거나 채널 목록을 ajax 로 로드하는 경우 등 그럴 수 없는 상황에서는 선택한 채널의 이름을 어딘가 페이지 이동간에도 지워지지 않는 공간에 저장할 필요가 있다.

window.name 값을 읽고 쓰는 방법으로 session 을 흉내낼 수 있다.
참조: http://blogs.sitepoint.com/javascript-session-variable-library/

window.name 에 스트링으로 값을 읽고 쓰고 할 수 있고 페이지 이동간에도 값은 바뀌지 않는다.

저장하려는 값이 많고 복잡한 경우 json(javascript 코드를 스트링으로 변경 또는 반대로 변경 가능한 포맷) 을 이용하여 javascript 코드를 스트링으로 변경하여 값을 저장하고 읽을 때는 javascript 코드로 변경하는 방법을 사용한다.
참조: http://blogs.sitepoint.com/javascript-json-serialization/

아마도 iframe 태그를 사용하거나 frame 을 사용하는 경우 window.name 값이 각 페이지 마다 다를 수 있다.
이런 경우 window.top.name 에 값을 저장한다.

2010년 10월 24일 일요일

Javascript 문법 검사 및 압축

Javascript 문법 검사해 주는 사이트 - http://jslint.com/

Javascript 를 압축해 주는 사이트 - http://fmarcia.info/jsmin/test.html

  • html 에 포함하는 javascript 의 글자수(데이터 크기)는 웹페이지 로딩 시간에 영향을 준다.
  • 그렇기 때문에 공백 문자나 개행 문자 등의 코드를 알아보기 쉽게하지만 데이터 크기를 늘리는 문자들을 제거할 필요가 있다.