ScrollList Module1

ScrollList´Â ÀÚÁÖ »ç¿ëµÇ±â ¶§¹®¿¡ °øÅë ¸ðµâ·Î ÀÛ¼º ÇÏ¿´´Ù.

ScrollList Prototype

function clamp(value, min, max) {
    if(value < min)
        value = min;
    else if(value > max)
        value = max;
        return value;
}


function ScrollList(viewName, focusClassName, selectClassName) {
    this.index = -1;
    this.viewName = viewName;
    this.focusClassName = focusClassName;
    this.keyHandler = this.onKeyDown.bind(this);
    if(selectClassName)
        this.selectClassName = selectClassName;
    else
        this.selectClassName = focusClassName;
    this.view = null;
    this.index = 0;
}

ScrollList.prototype.init = function() {
    this.view = document.getElementById(this.viewName);
    if(this.view.children.length > 0)
        this.view.children[0].classList.add(this.selectClassName);
    //window.addEventListener("keydown", this.onKeyDown.bind(this));
}

ScrollList.prototype.isFocus = function() {
    let index = this.index;
    if(index < 0)
        return false;
    return this.view.children[index].classList.contains(this.focusClassName);
}

ScrollList.prototype.focus = function(flag) {
    let index = this.index;
    if(flag) {
        this.view.children[index].classList.remove(this.selectClassName);
        this.view.children[index].classList.add(this.focusClassName);
        window.addEventListener("keydown", this.keyHandler);
    }
    else {
        this.view.children[index].classList.remove(this.focusClassName);
        this.view.children[index].classList.add(this.selectClassName);
        window.removeEventListener("keydown", this.keyHandler);
    }
}

ScrollList.prototype.onKeyDown = function(e) {
    let move = 0;
    if (e.which == 37) { // left arrow
    }
    else if (e.which == 38) { // up arrow
        move = -1;
    }
    else if (e.which == 39) { // right arrow
    }        
    else if (e.which == 40) { // down arrow
        move = 1;
    }
    else if(e.keyCode === 13) {
    }
    
    let oldIndex = this.index;
    this.index += move;
    this.index = clamp(this.index, 0, this.view.children.length - 1);
    this.scroll(oldIndex, this.index);
}

ScrollList.prototype.scroll = function(oldIndex, curIndex) {
    let view = this.view;
    let index = this.index;
    if(view.children.length < 2)
        return;
        
    view.children[oldIndex].classList.remove(this.focusClassName);
    view.children[index].classList.add(this.focusClassName);

    var h1 = view.children[0].offsetTop;
    var h2 = view.children[1].offsetTop;
    var itemHeight = h2 - h1;     
    
    var gap = (curIndex+1)*itemHeight - view.scrollTop;
    var move = curIndex - oldIndex;

    if(move > 0 && gap > view.offsetHeight) {
        view.scrollTop = (curIndex+1)*itemHeight - view.offsetHeight;
    }
    
    if  (move < 0 && gap - itemHeight < 0) {
        view.scrollTop = itemHeight*index;
    }
}

new·Î »ý¼ºÇÑ ¿ÀºêÁ§Æ®ÀÇ °æ¿ì, addEventListener, removeEventListener ÇÒ¶§ ÁÖÀÇ ÇØ¾ß ÇÑ´Ù.
this.onKeyDown.bind(this) È£Ãâ ÇÒ¶§¸¶´Ù »õ·Î¿î °ª°ú ÇÔ¼ö¸¦ ¹Ýȯ ÇÑ´Ù.
´ÙÀ½°ú °°ÀÌ ½ÇÇàÇϸé removeEventListener°¡ Á¤»óÀûÀ¸·Î ½ÇÇà µÇÁö ¾Ê´Â´Ù.

window.addEventListener("keydown", this.onKeyDown.bind(this));
window.removeEventListener("keydown", this.onKeyDown.bind(this));

´ÙÀ½°ú °°ÀÌ º¯¼ö·Î µé°í ÀÖÀ¸¸é µ¿ÀÏÇÑ °ª°ú ÇÔ¼ö¸¦ ¸Å°³º¯¼ö·Î ³Ñ°Ü ÁÙ¼ö Àֱ⠶§¹®¿¡ removeEventListener°¡ Á¤»óÀûÀ¸·Î ½ÇÇàÀÌ µÈ´Ù.

this.keyHandler = this.onKeyDown.bind(this);

window.addEventListener("keydown", this.keyHandler);
window.removeEventListener("keydown", this.keyHandler);

»ç¿ë¹ý

¿£ÅÍÅ°¸¦ ´©¸£¸é ¸®½ºÆ® Æ÷Ä¿½º°¡ ¹Ù²ï´Ù.
À§, ¾Æ·¡ È­»ìÇ¥ Å°¸¦ ´©¸£¸é Æ÷Ä¿½º°¡ À§, ¾Æ·¡·Î À̵¿ ÇÑ´Ù.



ScrollList¸¦ new·Î »ý¼ºÇÑ´Ù.

function ScrollList(viewName, focusClassName, selectClassName)
viewName : scroll ¿ä¼Ò À̸§
focusClassName :  Æ÷Ä¿½ºµÈ ½ºÅ©·Ñ ¾ÆÀÌÅÛÀÇ Å¬·¡½º ½ºÅ¸ÀÏ À̸§
selectClassName :  ¸¶Áö¸·À¸·Î Æ÷Ä¿½ÌµÈ ¾ÆÀÌÅÛÀ¸·Î, ¼±ÅõǴ ¾ÆÀÌÅÛÀÇ ½ºÅ¸ÀÏ À̸§ÀÌ´Ù.
                          Æ÷Ä¿½º°¡ »ç¶óÁö¸é selectClassName ½ºÅ¸ÀÏ·Î ¹Ù²ï´Ù.
                          selectClassNameÀ» »ý·«Çϸé focusClassName°ú µ¿ÀÏÇÑ °ªÀÌ Àû¿ëµÈ´Ù.

¿¹)
let scrollList = new ScrollList('scrolltest', 'focusElement', 'selectElement');
scrollList.init();

<style>
#scrolltest>div {
    margin: 30px;
    height: 100px;
    border: 2px solid black;
    box-sizing:border-box;
}

#scrolltest_two {
    position: absolute;
    display: block;
    background: yellow;
    width: 200px;
    height:500px;
    top: 200px;
    left: 600px;  
    overflow:auto;
}

#scrolltest_two>div {
    margin: 30px;
    height: 100px;
    border: 2px solid black;
    box-sizing:border-box;
}
</style>

<div id="scrolltest">
    <div>0</div>   
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
    <div>10</div>
    <div>11</div>
    <div>12</div>
    <div>13</div>
    <div>14</div>
    <div>15</div>
    <div>16</div>
    <div>17</div>
    <div>18</div>
    <div>19</div>
</div>

<div id="scrolltest_two">
    <div>0</div>   
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
    <div>10</div>
    <div>11</div>
    <div>12</div>
    <div>13</div>
    <div>14</div>
    <div>15</div>
</div>

<script>
let scrollList = new ScrollList('scrolltest', 'focusElement', 'selectElement');
scrollList.init();
scrollList.focus(true);

let scrollListTwo = new ScrollList('scrolltest_two', 'focusElement', 'selectElement');
scrollListTwo.init();

var onKeyDown = function(e) {
    if(e.keyCode === 13) {
        if(scrollList.isFocus()) {
           scrollList.focus(false);
           scrollListTwo.focus(true);
        }
        else {
           scrollList.focus(true);
           scrollListTwo.focus(false);       
        }
    }
}

document.addEventListener("keydown", onKeyDown);
</script>

´Ù¿î·Îµå: ui_statePattern1.html

keydown À̺¥Æ® Á¦°Å ¹öÀü

keydown À̺¥Æ®¸¦ ¿ÜºÎ¿¡¼­ Çϴ°ɷΠº¯°æ ÇÏ¿´´Ù.
ScrollList¿¡¼­ addEventListener, removeEventListener¸¦ Á¦°Å ÇÏ¿´´Ù.

function clamp(value, min, max) {
    if(value < min)
        value = min;
    else if(value > max)
        value = max;
        return value;
}

function ScrollList(viewName, focusClassName, selectClassName) {
    this.index = -1;
    this.viewName = viewName;
    this.focusClassName = focusClassName;
    if(selectClassName)
        this.selectClassName = selectClassName;
    else
        this.selectClassName = focusClassName;
    this.view = null;
    this.index = 0;
}

ScrollList.prototype.init = function() {
    this.view = document.getElementById(this.viewName);
    if(this.view.children.length > 0)
        this.view.children[0].classList.add(this.selectClassName);
}

ScrollList.prototype.isFocus = function() {
    let index = this.index;
    if(index < 0)
        return false;
    return this.view.children[index].classList.contains(this.focusClassName);
}

ScrollList.prototype.focus = function(flag) {
    let index = this.index;
    if(flag) {
        this.view.children[index].classList.remove(this.selectClassName);
        this.view.children[index].classList.add(this.focusClassName);
    }
    else {
        this.view.children[index].classList.remove(this.focusClassName);
        this.view.children[index].classList.add(this.selectClassName);
    }
}

ScrollList.prototype.onKeyDown = function(e) {
    let move = 0;
    if (e.which == 37) { // left arrow
    }
    else if (e.which == 38) { // up arrow
        move = -1;
    }
    else if (e.which == 39) { // right arrow
    }       
    else if (e.which == 40) { // down arrow
        move = 1;
    }
    else if(e.keyCode === 13) {
    }
   
    let oldIndex = this.index;
    this.index += move;
    this.index = clamp(this.index, 0, this.view.children.length - 1);
    this.scroll(oldIndex, this.index);
}

ScrollList.prototype.scroll = function(oldIndex, curIndex) {
    let view = this.view;
    let index = this.index;
    if(view.children.length < 2)
        return;
       
    view.children[oldIndex].classList.remove(this.focusClassName);
    view.children[index].classList.add(this.focusClassName);

    var h1 = view.children[0].offsetTop;
    var h2 = view.children[1].offsetTop;
    var itemHeight = h2 - h1;    
   
    var gap = (curIndex+1)*itemHeight - view.scrollTop;
    var move = curIndex - oldIndex;

    if(move > 0 && gap > view.offsetHeight) {
        view.scrollTop = (curIndex+1)*itemHeight - view.offsetHeight;
    }
   
    if  (move < 0 && gap - itemHeight < 0) {
        view.scrollTop = itemHeight*index;
    }
}

let scrollList = new ScrollList('scrolltest', 'focusElement', 'selectElement');
scrollList.init();
scrollList.focus(true);

let scrollListTwo = new ScrollList('scrolltest_two', 'focusElement', 'selectElement');
scrollListTwo.init();

var onKeyDown = function(e) {
    if(e.keyCode === 13) {
        if(scrollList.isFocus()) {
           scrollList.focus(false);
           scrollListTwo.focus(true);
        }
        else {
           scrollList.focus(true);
           scrollListTwo.focus(false);       
        }
    }
    else {
        if(scrollList.isFocus())
            scrollList.onKeyDown(e);
        else if(scrollListTwo.isFocus())
            scrollListTwo.onKeyDown(e);
    }
}

document.addEventListener("keydown", onKeyDown);

´Ù¿î·Îµå: ui_statePattern2.html

ÂüÁ¶)
javascript removeEventListener not working inside a class
https://stackoverflow.com/questions/33859113/javascript-removeeventlistener-not-working-inside-a-class