Hunter Mitchell Hunter Mitchell - 3 months ago 12
jQuery Question

Infinite header in JavaScript?

I am facing a unique problem (probably apparent by my odd title) which I have been unable to figure out a good (efficient) solution to.

Basically, I have a list which needs to scroll either to the left or right (basically like something you would see in Microsoft Excel or Google Sheets).

Anything to the left will be something like

-A, -B, ..
and anything to the right will continue like
A, B, C, .. , AA, AB, AC, etc.


enter image description here

As of now, I am incrementing the
left
style to move the list, however i need some way of adding/removing elements on this list (would continually adding and removing elements degrade performance?)

I am needing an efficient way of making this infinite.


JSFIDDLE



// Calculate the minimum number of sections
var minSections = document.documentElement.clientWidth / 150; // because each rule is 150px wide

// Initially create our first row
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
for (var index = 0; index < minSections; index++) {
$("#header").append("<li>" + alphabet[index] + "</li>")
}

document.onkeydown = function myFunction() {
switch (event.keyCode) {
case 37:
document.getElementById("header").style.left = ((parseInt(document.getElementById("header").style.left, 10) || 0) - 10) + "px";
break;
case 39:
document.getElementById("header").style.left = ((parseInt(document.getElementById("header").style.left, 10) || 0) + 10) + "px";
break;
}
}


// At this point I am not sure what the best (more efficient) approach to this issue is.

html, body {margin: 0; padding: 0;}

.container {
background: #444;
padding: 5px 3px;
overflow: hidden;
white-space: nowrap;
}

ul {
position: relative;
margin: 0;
padding: 0;
list-style: none;
text-transform: uppercase;
}

ul li {
display: inline-block;
width: 150px;
text-align:center;
color: #FFF;
border-left: 1px solid #FFF;
box-sizing: border-box;
}

ul li:first-child {
border: none;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<ul id="header">
</ul>
</div>





NOTE: On the above snippet I am emulating a pan with the left and right arrow keys (these will be used to move/scroll the list)

Answer

You can simply add a prepend/append to your alphabet and #header in your onkeydown event.

See fiddle: https://jsfiddle.net/vrff4kfo/1/

// Calculate the minimum number of sections
var ruleWidth = 150; // because each rule is 150px wide
var minSections = Math.ceil(document.documentElement.clientWidth / ruleWidth); 
var leftMost = 0;
var rightMost = minSections;

// Initially create our first row
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
for (var index = 0; index < minSections; index++) {
    $("#header").append("<li>" + alphabet[index] + "</li>")
}

document.onkeydown = function myFunction() {
    var left = parseInt(document.getElementById("header").style.left,10);
    switch (event.keyCode) {
        case 37:
            document.getElementById("header").style.left = ((left || 0) - 10) + "px";
            break;
        case 39:
            document.getElementById("header").style.left = ((left || 0) + 10) + "px";
            break;
    }
  if(left > ruleWidth){
    // Prepend a column
    leftMost++;
    $("#header").prepend("<li>-" + alphabet[leftMost-1] + "</li>");
    document.getElementById("header").style.left= left-ruleWidth + "px";
  }
  if(Math.ceil(minSections + (-left/ruleWidth)) > rightMost){
    //append a column
    rightMost= Math.ceil(minSections + (-left/ruleWidth));
    $("#header").append("<li>" + alphabet[rightMost] + "</li>");
  }
}

Once you go past the length of the alphabet in either direction you will of course need to programatically edit the alphabet.