I have a question. I've been working on a new JS game, and have just barely even started, and I ran into a hurdle:
var block = new Array(35);
var blockdata = new Array(35);
var count = 0;
var rand = 0;
while (count <= 35) {
rand = Math.floor((Math.random() * 3) + 1);
if (rand == 1) {
block[count] = "images/t.jpg";
} else {
block[count] = "images/g.jpg";
}
count++;
}
count = 0;
while (count <= 35) {
blockdata[count] = document.createElement("IMG");
blockdata[count].setAttribute("src", block[count]);
blockdata[count].position = "relative";
document.body.appendChild(blockdata[count]);
//inneficient code below XD
if (count == 5) {
var mybr = document.createElement('br');
document.body.appendChild(mybr);
}
if (count == 11) {
var mybr = document.createElement('br');
document.body.appendChild(mybr);
}
if (count == 17) {
var mybr = document.createElement('br');
document.body.appendChild(mybr);
}
if (count == 23) {
var mybr = document.createElement('br');
document.body.appendChild(mybr);
}
if (count == 29) {
var mybr = document.createElement('br');
document.body.appendChild(mybr);
}
count++;
}
#content {
line-height: 10px;
}
<script type="text/javascript" src="http://gc.kis.scr.kaspersky-labs.com/AA4B3110-75F6-C945-9AFA-B001BE396F4E/main.js" charset="UTF-8"></script>
<div id="content">
The game running can be seen here
The images (t.jpg, g.jpg) are put in rows. I do not want a tiny space between the rows, which you could see from the URL above.
I tried using CSS to make it work, but it won't.
Thanks for the help!
Image element is by default inline-block (display: inline-block). This adds this margin at the bottom. You could add margin-bottom: -4px to img, or you can make it display: block, but that would break your layout and you will need to use float: left on image or use some other css like display: flex on images parent.
And ofc, remove <br>
I have a solution, thanks to Kantoci.
I kept all the code the same, but I added some CSS:
img {
margin-bottom: -4px
}
The other CSS code was unnecessary, and all the <div> tags were not required.
It is actually because of <br> tag you are adding.
if you want to break without any space then alternate way is to use
<ul><li> tag.
then in each li you can mention how many blocks needed.
following way can be done:
update style block like this-
<style>
body,
ul,
ul li {
padding: 0px;
margin: 0px;
}
#content {
line-height: 10px;
}
</style>
<body>
<ul id="content">
</ul>
<script>
var block = new Array(35);
var blockdata = new Array(35);
var count = 0;
var rand = 0;
while (count <= 35) {
rand = Math.floor((Math.random() * 3) + 1);
block[count] = rand == 1 ? "images/t.jpg" : "images/g.jpg";
count++;
}
count = 0;
var gap = 1;
var list = "<li>";
while (count <= 35) {
var isLimit = (count > 0 && (5 * gap) + (gap - 1) == count)
list += isLimit ? "<img src=" + block[count] + "></li><li>" : "<img src=" + block[count] + ">";
gap = isLimit ? gap + 1 : gap;
count++;
}
var content = document.getElementById("content");
content.innerHTML = list;
</script>
Related
I created a grid with random boxes, yellow and one red.
The problem is that when I refresh the page sometimes the red box doesn't appear, is hidden somewhere, I guess under a yellow box. Also, sometimes even the yellow boxes are not all displayed.
I guess there's a problem in the loop to create them?
var grid = document.getElementById("grid-box");
for (var i = 1; i <= 100; i++) {
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var obstacles = [];
while (obstacles.length < 10) {
var randomIndex = parseInt(99 * Math.random());
if (obstacles.indexOf(randomIndex) === -1) {
obstacles.push(randomIndex);
document.getElementById('square' + randomIndex).style.backgroundColor = 'yellow';
}
}
var playerOne = [];
while (playerOne.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerOne.indexOf(randomIndex) === -1) {
playerOne.push(randomIndex);
document.getElementById('square' + randomIndex).style.backgroundColor = 'red';
}
}
#grid-box {
width: 400px;
height: 400px;
margin: 0 auto;
font-size: 0;
position: relative;
}
#grid-box>div.square {
font-size: 1rem;
vertical-align: top;
display: inline-block;
width: 10%;
height: 10%;
box-sizing: border-box;
border: 1px solid #000;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<div id="grid-box"></div>
You have to change 2 things:
1. initial value of i should be 0 when you create squares
2. when you make red box then
replace
if (playerOne.indexOf(randomIndex)
with
if (playerOne.indexOf(randomIndex) === -1 && obstacles.indexOf(randomIndex) === -1) {
Here is the final code:
var grid = document.getElementById("grid-box");
// create 100 squares
for (var i = 0; i < 100; i++) { // first change
var square = document.createElement("div");
square.className = 'square';
square.id = 'square' + i;
grid.appendChild(square);
}
var obstacles = [];
while (obstacles.length < 10) {
var randomIndex = parseInt(99 * Math.random());
if (obstacles.indexOf(randomIndex) === -1) {
obstacles.push(randomIndex);
document.getElementById('square' + randomIndex).style.backgroundColor = 'yellow';
}
}
var playerOne = [];
while (playerOne.length < 1) {
var randomIndex = parseInt(99 * Math.random());
if (playerOne.indexOf(randomIndex) === -1 && obstacles.indexOf(randomIndex) === -1) { // second change
playerOne.push(randomIndex);
document.getElementById('square' + randomIndex).style.backgroundColor = 'red';
}
}
It is because, when randomIndex would be zero(0), then you are searching element whose id is "square0" and it is not available because your for loop starts runs from 1 to 100.
Math.random() would sometimes return 0, but your ids are starting from 1 eg: 'square1', there is no 'square0' div.
Make your loop starts from 0:
for (var i = 0; i < 100; i++){
// Code here
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Background: I am working on a dashboard, which shows a header and a table underneath. The table can have many rows (over 100).
Problem: large number of rows triggers a vertical scrollbar to show up, which hides the rest of the rows.
Possible solution: I would like to rotate, what table rows are showed on every screen the dashboard is on. I would like to avoid to set a fixed number of rows that are visible on screen and instead, determine how many rows can be put on the screen before the scroll bar shows up. This means that, first, I would like to determine how many rows are visible on the screen before the scrollbar shows up, and then create a carousel animation, where the next X rows are showed until all the rows are showed and the animation resets.
Technologies used: React JS, Bootstrap table
For the carousel part, I found Bootstrap Carousel to work fine, but the problem is figuring out, how many rows are visible on the screen. How do I determine, how many rows I can display on the screen before the scroll-bar shows up? Thank you very much!
One possible solution would be:
Create an element in the DOM which would be 100% height (any other possible height will work too). For example:
<div id="row-wrapper" style="height: 100%"></div>
Get the height of the element.
var availableHeight = document.getElementById('row-wrapper').clientHeight;
Knowing how much height your single row occupies just divide availableHeight and you will know how many rows to render. In case your row height is 30:
var numberOfRows = Math.floor(availableHeight / 30);
I know you tagged ReactJS, but a good basis is to always keep your DOM as small as possible. My tactic would be to keep the data in JavaScript and only introduce to the DOM what is absolutely needed.
Below is a simple example showing 10 rows with an offset:
var dummyData = [];
(function populateData() {
var names = ["Greg", "Jeff", "Bob", "Bruce", "Clark", "Diana"];
while (dummyData.length < 100000) {
dummyData.push({
name: names[Math.floor(Math.random() * names.length)],
age: Math.floor(Math.random() * 100)
});
}
})();
function displayData(data, offset, limit) {
if (offset === void 0) {
offset = 0;
}
if (limit === void 0) {
limit = data.length;
}
var tbody = document.body.appendChild(document.createElement("tbody"));
for (var i = offset; i < (limit + offset); i++) {
if (i >= data.length) {
break;
}
var person = data[i];
var tr = tbody.appendChild(document.createElement("tr"));
tr.innerHTML = "<td>" + i + "</td><td>" + person.name + "</td><td>" + person.age + "</td>";
}
return tbody;
}
var pagesize = 10;
var offset = 0;
var offsetInput = document.body.appendChild(document.createElement("input"));
offsetInput.type = "number";
offsetInput.min = "0";
offsetInput.value = "0";
var table = document.body.appendChild(document.createElement("table"));
table.style.width = "100%";
table.innerHTML = "<thead><tr><th>Index</th><th>Name</th><th>Age</th></tr></thead>";
var tbody = table.appendChild(displayData(dummyData, offset, pagesize));
function update() {
if (offsetInput.validity.valid) {
offset = parseInt(offsetInput.value, 10);
table.removeChild(tbody);
tbody = displayData(dummyData, offset, pagesize);
table.appendChild(tbody);
}
}
offsetInput.addEventListener("change", update);
offsetInput.addEventListener("keyup", update);
From here it would be a matter of some CSS tricking and reading the scrollbar to get an offset.
var dummyData = [];
(function populateData() {
var names = ["Greg", "Jeff", "Bob", "Bruce", "Clark", "Diana"];
while (dummyData.length < 100) {
dummyData.push({
name: names[Math.floor(Math.random() * names.length)],
age: Math.floor(Math.random() * 100)
});
}
})();
function displayData(data, offset, limit) {
if (offset === void 0) {
offset = 0;
}
if (limit === void 0) {
limit = data.length;
}
var tbody = document.body.appendChild(document.createElement("tbody"));
for (var i = offset; i < (limit + offset); i++) {
if (i >= data.length) {
break;
}
var person = data[i];
var tr = tbody.appendChild(document.createElement("tr"));
tr.innerHTML = "<td>" + i + "</td><td>" + person.name + "</td><td>" + person.age + "</td>";
}
return tbody;
}
var pagesize = 10;
var offset = 0;
var offsetInput = document.body.appendChild(document.createElement("input"));
offsetInput.type = "number";
offsetInput.min = "0";
offsetInput.max = "" + (dummyData.length - pagesize);
offsetInput.value = "0";
var outerContainer = document.body.appendChild(document.createElement("div"));
outerContainer.style.maxHeight = "400px";
outerContainer.style.width = "450px";
outerContainer.style.overflowY = "scroll";
var innerContainer = outerContainer.appendChild(document.createElement("div"));
innerContainer.style.height = dummyData.length * 20 + 200 + "px";
var table = innerContainer.appendChild(document.createElement("table"));
table.style.position = "absolute";
table.style.width = "400px";
table.innerHTML = "<thead><tr><th>Index</th><th>Name</th><th>Age</th></tr></thead>";
var tbody = table.appendChild(displayData(dummyData, offset, pagesize));
var handle;
function update() {
table.removeChild(tbody);
tbody = displayData(dummyData, offset, pagesize);
table.appendChild(tbody);
clearTimeout(handle);
handle = setTimeout(function() {
offsetInput.value = offset.toString();
outerContainer.scrollTop = offset * 20;
}, 100);
}
function updateInput() {
if (offsetInput.validity.valid) {
offset = parseInt(offsetInput.value, 10);
}
update();
}
function updateScroll() {
offset = Math.floor(outerContainer.scrollTop / 20);
update();
}
outerContainer.addEventListener("scroll", updateScroll);
offsetInput.addEventListener("change", updateInput);
offsetInput.addEventListener("keyup", updateInput);
This is an example how you can fill a div until its full. Made a jQuery answer too if someone is interested in that.
I made 2 div's. One with a set height(100% in the example but can be static height too) and inside a growable div that grows with the content.
First it will fill the growable div as long it is smaller then the content div.
The last added element could be bigger then the remaining space. If that happens it removes the last element.
This also works with content with dynamic heights.
Note: When using while loops it's always good to have a backup plan to avoid infinite loops. Therefore I added a max records variable.
Javascript:
window.onload = function() {
document.getElementById('fill').onclick = function() {
var content = document.getElementById('content');
var growableWrapper = document.getElementById('growableWrapper');
var maxRecords = 50;
while ((content.childNodes.length === 0 || parseInt(window.getComputedStyle(growableWrapper).height) < parseInt(window.getComputedStyle(content).height)) && growableWrapper.childNodes.length < maxRecords) {
var newElement = document.createElement("p");
var newText = document.createTextNode("Test");
newElement.appendChild(newText);
growableWrapper.appendChild(newElement);
}
if (window.getComputedStyle(growableWrapper).height > window.getComputedStyle(content).height && growableWrapper.childNodes.length > 1) {
growableWrapper.removeChild(growableWrapper.childNodes[growableWrapper.childNodes.length - 1]);
}
}
}
html,
body,
#content {
margin: 0;
padding: 0;
height: 100%;
}
#fill,
#content {
width: 40%;
float: left;
}
#content {
background-color: gray;
overflow: hidden;
}
#growableWrapper {
background-color: lightgray;
overflow: auto;
}
<div>
<button id="fill">Fill</button>
</div>
<div id="content">
<div id="growableWrapper">
</div>
</div>
jQuery:
$(document).ready(function() {
$('#fill').on('click', function() {
var content = $('#content');
var growableWrapper = $('#growableWrapper');
var maxRecords = 50;
while ((content.children().length === 0 || growableWrapper.height() < content.height()) && growableWrapper.children().length < maxRecords) {
growableWrapper.append('<p>test</p>');
}
if(growableWrapper.height() > content.height() && growableWrapper.children().length > 1) {
growableWrapper.children().last().remove();
}
});
});
html,
body,
#content {
margin: 0;
padding: 0;
height: 100%;
}
#fill, #content {
width: 40%;
float: left;
}
#content {
background-color: gray;
overflow: hidden;
}
#growableWrapper {
background-color: lightgray;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<button id="fill">Fill</button>
</div>
<div id="content">
<div id="growableWrapper">
</div>
</div>
What I'm trying to do is write a function that will iterate over all different html elements which have a class name beginning with rnum- followed by a number. A complete example of a span would be <span class="rnum-293"></span>.
I then want to implement the function that I have written below and have it do the increasing effect up to each of their given numbers(specified in the class name).
Does anyone have an idea how I can achieve this? Thanks!
var count = 0;
var target = 126;
var increment = target / 198;
var elements = document.getElementsByClassName('rnum');
function calc() {
if(count < target) {
count += increment;
}
for(var i = 0; i < elements.length; i++) {
elements[i].innerHTML = Math.round(count);
}
}
setInterval(calc, 10)
#import url('https://fonts.googleapis.com/css?family=Bangers');
body {
font-family: 'Bangers';
display: flex;
align-items: center;
justify-content: center;
}
.rnum {
font-size: 55px;
margin: 50px;
}
<span class="rnum"></span>
<span class="rnum"></span>
<span class="rnum"></span>
To select the elements, use:
var elements = document.querySelectorAll('[class^="rnum-"]');
Or, if only span elements, use:
var elements = document.querySelectorAll('span[class^="rnum-"]');
I am unsure about the second part of your question. For all I see, the only issue was selecting the elements.
For the second part:
JavaScript:
var elements = document.querySelectorAll('span[class^="rnum-"]');
function calc() {
var el = null;
var val = 0;
var currentValue = 0;
var incrementFactor = 198;
var increment = 0;
var maxValue = 0;
for (var i = 0, len = elements.length; i < len; i++) {
el = elements[i];
maxValue = Number(el.getAttribute('data-max-val'));
currentValue = Number(el.getAttribute('data-current-val'));
increment = maxValue / incrementFactor;
if ((currentValue + increment) > maxValue)
continue;
val = currentValue + increment;
el.innerHTML = Math.round(val);
el.setAttribute('data-current-val', Math.round(val));
}
}
setInterval(calc, 10)
HTML:
<span class="rnum-198000" data-current-val="0" data-max-val="198000">0</span>
<span class="rnum-299000" data-current-val="0" data-max-val="299000">0</span>
<span class="rnum-399000" data-current-val="0" data-max-val="399000">0</span>
<span class="rnum-499000" data-current-val="0" data-max-val="499000">0</span>
Pen: http://codepen.io/anon/pen/rjyqMd?editors=1111
I am trying to make a chess game. So far i have only made the white pawns moveable (you move them by dragging them to where you want them to go). However, only the first move works. Why does this happen? I use
$(".piece").mousedown(function(){}
, but it is only called once.
The problem is $("#" + tileFn).append($("#" + tileIn).html()); which creates a new piece element, to whom the mousedown handler is not attached.
One solution is to use event deletagation, or instead of creating a new element just move the existing element like
function parent(element) {
var parentID = $(element).parent().attr("ID");
var parentClass = $(element).parent().attr("class");
var parentType = $(element).parent().get(0).nodeName;
if (parentID != null) {
return ("#" + parentID);
} else if (parentClass != null) {
return ("." + parentClass);
} else {
if (parentType.toLowerCase() == "body") {
parentType = document;
return parentType;
} else {
return parentType;
}
}
}
var dimensions = 600; // must be divisible by 8
var tile1 = "<div class='tile tile1' id='";
var tile2 = "<div class='tile tile2' id='";
var end = "'></div>";
var multiplicity = "";
var tileIn = "";
var tileFi = "";
var classes = "";
var color = "";
var type = "";
var possible = [];
$(document).ready(function() {
//setup start
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
row = i * 2 + 1;
column = j * 2 + 1;
$("#container").append(tile1 + row + column + end + tile2 + row + (column + 1) + end);
}
for (var k = 0; k < 4; k++) {
row = i * 2 + 2;
column = k * 2 + 1;
$("#container").append(tile2 + row + column + end + tile1 + row + (column + 1) + end);
}
}
$("#container").css({
height: dimensions,
width: dimensions
});
$(".tile").css({
height: dimensions / 8,
width: dimensions / 8
});
$(".piece").css({
height: dimensions / 8,
width: dimensions / 8
});
$("<div class='b p piece'><img src='bp.icns' height='69'></div>").appendTo("#21, #22, #23, #24, #25, #26, #27, #28");
$("<div class='b r piece'><img src='br.icns' height='69'></div>").appendTo("#11, #18");
$("<div class='b n piece'><img src='bn.icns' height='69'></div>").appendTo("#12, #17");
$("<div class='b b piece'><img src='bb.icns' height='69'></div>").appendTo("#13, #16");
$("<div class='b k piece'><img src='bk.icns' height='69'></div>").appendTo("#14");
$("<div class='b q piece'><img src='bq.icns' height='69'></div>").appendTo("#15");
$("<div class='w p piece'><img src='wp.icns' height='69'></div>").appendTo("#71, #72, #73, #74, #75, #76, #77, #78");
$("<div class='w r piece'><img src='wr.icns' height='69'></div>").appendTo("#81, #88");
$("<div class='w n piece'><img src='wn.icns' height='69'></div>").appendTo("#82, #87");
$("<div class='w b piece'><img src='wb.icns' height='69'></div>").appendTo("#83, #86");
$("<div class='w q piece'><img src='wq.icns' height='69'></div>").appendTo("#84");
$("<div class='w k piece'><img src='wk.icns' height='69'></div>").appendTo("#85");
//setup end
$(".piece").mousedown(function() {
tileIn = parent($(this)).substr(1, 2);
classes = $(this).attr("class");
color = classes.charAt(0);
type = classes.charAt(2);
y = tileIn.charAt(0);
x = tileIn.charAt(1);
//white start
if (color == "w") {
//white pawn start
if (type == "p") {
if (y == "7") {
possible = ["6" + x, "5" + x];
} else {
possible = [(y - 1) + x];
}
return;
}
//white pawn end
//
else if ("a" == "b") {
}
}
//white end
//black start
else {
}
//white end
});
$(".tile").mouseup(function() {
tileFn = $(this).attr("id");
if (jQuery.inArray(tileFn, possible) !== -1 && $(this).is(':empty')) {
$("#" + tileFn).append($("#" + tileIn).contents());
} else {}
possible = [];
});
});
* {
user-drag: none;
-moz-user-select: none;
-webkit-user-drag: none;
}
#container {
margin: 0 auto;
border: 1px solid gray;
}
.tile {
float: left;
}
.tile1 {
background-color: white;
}
.tile2 {
background-color: rgba(0, 0, 0, 0.58);
}
.piece {
padding: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css">
<div id="container"></div>
The selector $(".piece") only selects the fields which has pices on it at the time you execute the statement. You will have to add the function to the fields as the pieces are moved on the board.
So you mouseup function should probably set the call back for the piece on the new field.
I am trying to render the list based on virtual rendering concept. I am facing some minor issues, but they are not blocking the behaviour. Here is the working fiddle http://jsfiddle.net/53N36/9/ and Here are my problems
Last items are not visible, I assume some where I missed indexing.(Fixed, Please see the edit)
How to calculate scrollPosition if I want to add custom scroll to this.
Is this the best method or any other?
I have tested it with 700000 items and 70 items in chrome. Below is the code
(function () {
var list = (function () {
var temp = [];
for (var i = 0, l = 70; i < l; i++) {
temp.push("list-item-" + (i + 1));
}
return temp;
}());
function listItem(text, id) {
var _div = document.createElement('div');
_div.innerHTML = text;
_div.className = "listItem";
_div.id = id;
return _div;
}
var listHold = document.getElementById('listHolder'),
ht = listHold.clientHeight,
wt = listHold.clientWidth,
ele = listItem(list[0], 'item0'),
frag = document.createDocumentFragment();
listHold.appendChild(ele);
var ht_ele = ele.clientHeight,
filled = ht_ele,
filledIn = [0];
for (var i = 1, l = list.length; i < l; i++) {
if (filled + ht_ele < ht) {
filled += ht_ele;
ele = listItem(list[i], 'item' + i);
frag.appendChild(ele);
} else {
filledIn.push(i);
break;
}
}
listHold.appendChild(frag.cloneNode(true));
var elements = document.querySelectorAll('#listHolder .listItem');
function MouseWheelHandler(e) {
var e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
console.log(delta);
//if(filledIn[0] != 0 && filledIn[0] != list.length){
if (delta == -1) {
var start = filledIn[0] + 1,
end = filledIn[1] + 1,
counter = 0;
if (list[start] && list[end]) {
for (var i = filledIn[0]; i < filledIn[1]; i++) {
if (list[i]) {
(function (a) {
elements[counter].innerHTML = list[a];
}(i));
counter++;
}
}
filledIn[0] = start;
filledIn[1] = end;
}
} else {
var start = filledIn[0] - 1,
end = filledIn[1] - 1,
counter = 0;
if (list[start] && list[end]) {
for (var i = start; i < end; i++) {
if (list[i]) {
(function (a) {
elements[counter].innerHTML = list[a];
}(i));
counter++;
}
}
filledIn[0] = start;
filledIn[1] = end;
}
}
//}
}
if (listHold.addEventListener) {
listHold.addEventListener("mousewheel", MouseWheelHandler, false);
listHold.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
} else listHold.attachEvent("onmousewheel", MouseWheelHandler);
}());
Please suggest me on this.
EDIT:
I have tried again and I am able to fix the indexing issue. http://jsfiddle.net/53N36/26/
But how can I calculate the scroll position based on the array list currently displayed.
Is this the best method or any other?
I think something that would make this much easier is not to try to handle scrolling yourself.
In this fiddle I show that you can let the browser handle scrolling for you, even though we are using virtual rendering.
Using .scrollTop I detect where the browser thinks the user is looking, and I draw in items based on that.
You'll note that if you set hidescrollbar to false and the user uses it to scroll, my method still runs fine.
Therefore, to calculate scroll position you can just use .scrollTop.
And as for custom scrolling, just make sure you influence the .scrollTop of #listHolder and recall refreshWindow()
CODE FROM FIDDLE
(function () {
//CHANGE THESE IF YOU WANT
var hidescrollbar = false;
var numberofitems = 700000;
//
var holder = document.getElementById('listHolder');
var view = null;
//get the height of a single item
var itemHeight = (function() {
//generate a fake item
var div = document.createElement('div');
div.className = 'listItem';
div.innerHTML = 'testing height';
holder.appendChild(div);
//get its height and remove it
var output = div.offsetHeight;
holder.removeChild(div);
return output;
})();
//faster to instantiate empty-celled array
var items = Array(numberofitems);
//fill it in with data
for (var index = 0; index < items.length; ++index)
items[index] = 'item-' + index;
//displays a suitable number of items
function refreshWindow() {
//remove old view
if (view != null)
holder.removeChild(view);
//create new view
view = holder.appendChild(document.createElement('div'));
var firstItem = Math.floor(holder.scrollTop / itemHeight);
var lastItem = firstItem + Math.ceil(holder.offsetHeight / itemHeight) + 1;
if (lastItem + 1 >= items.length)
lastItem = items.length - 1;
//position view in users face
view.id = 'view';
view.style.top = (firstItem * itemHeight) + 'px';
var div;
//add the items
for (var index = firstItem; index <= lastItem; ++index) {
div = document.createElement('div');
div.innerHTML = items[index];
div.className = "listItem";
view.appendChild(div);
}
console.log('viewing items ' + firstItem + ' to ' + lastItem);
}
refreshWindow();
document.getElementById('heightForcer').style.height = (items.length * itemHeight) + 'px';
if (hidescrollbar) {
//work around for non-chrome browsers, hides the scrollbar
holder.style.width = (holder.offsetWidth * 2 - view.offsetWidth) + 'px';
}
function delayingHandler() {
//wait for the scroll to finish
setTimeout(refreshWindow, 10);
}
if (holder.addEventListener)
holder.addEventListener("scroll", delayingHandler, false);
else
holder.attachEvent("onscroll", delayingHandler);
}());
<div id="listHolder">
<div id="heightForcer"></div>
</div>
html, body {
width:100%;
height:100%;
padding:0;
margin:0
}
body{
overflow:hidden;
}
.listItem {
border:1px solid gray;
padding:0 5px;
width: margin : 1px 0px;
}
#listHolder {
position:relative;
height:100%;
width:100%;
background-color:#CCC;
box-sizing:border-box;
overflow:auto;
}
/*chrome only
#listHolder::-webkit-scrollbar{
display:none;
}*/
#view{
position:absolute;
width:100%;
}