How to make horizontal margin between images constant in mosaic - javascript

I am trying to replicate a mosaic that can be found on many webpages. While looking for solutions to my problem I came accross a very good implementation on squarespace seen at https://native-demo.squarespace.com/images-native/. I have hosted my website containing the mosaic at http://alexstiles.000webhostapp.com.
My issue is that when you resize the window the horizontal spacing between the images flucuates like it has an animation instead of staying consistient. Although it sorts itself out if you resize slowly, rapid movements can cause the margin to be to large or small. This behavior is not present in the squarespace template. How can I remove this and make the margin consistient when resizing? I have already tried using css margins instead of javascript. I have added the javascript below to help.
let mosaic = document.getElementsByClassName("mosaic")[0]; // For a single mosaic for now
let numImages = 12;
let imageTopic = "design";
let originalImageTopic = "design";
let rowWidth = 3;
let scale = 1;
let mosaicLoader = document.getElementsByClassName("loader-container")[0]
let search = document.getElementById("search");
let searchBtn = document.getElementById("search-button");
let form = document.getElementsByTagName("form")[0];
function rem(rems) {
return rems * (16 * scale);
}
searchBtn.addEventListener("click", function(event) {
event.preventDefault();
searchResult(search.value);
});
search.addEventListener("click", function() {
form.classList.add("focused");
});
search.addEventListener("blur", function() {
form.classList.remove("focused");
});
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '13' || e.which == '13' || e.key === "Enter") {
e.preventDefault();
searchResult(search.value);
}
}
if (window.location.hash) {
let hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
search.value = hash;
searchResult(hash);
}
function searchResult(query) {
// Get and set query
query = ((query != "" && query != originalImageTopic) ? search.value : imageTopic);
imageTopic = query;
if (imageTopic != originalImageTopic) {
parent.location.hash = imageTopic;
document.getElementById("search-term").textContent = imageTopic + " pictures";
}
// Put up loader while fetching images
mosaicLoader.style.display = "flex";
// Remove old images
let length = mosaic.children.length;
while (mosaic.lastChild && length > 1) {
mosaic.removeChild(mosaic.lastChild);
length--;
}
// Create new images
let loadedImageNum = 0
for (let i = 0; i < numImages; i++) {
let image = document.createElement("img");
image.src = `https://source.unsplash.com/random?${imageTopic}/sig${i}/`;
mosaic.appendChild(image);
}
// Wait for all images to load
let loadedImages = 0;
let image = mosaic.querySelectorAll("img");
imageCheck = setInterval(function() {
for (let i = 0; i < numImages; i++) {
if (image[i].naturalHeight !== 0 && image[i].complete) {
loadedImages++;
}
if (loadedImages == numImages) {
clearInterval(imageCheck);
// alert("Loaded!")
// Lay them out
setTimeout(imagesLoaded, 2000); // Needs some time before laying out
// Break loop
break;
}
}
}, 200)
}
searchResult(imageTopic); // Inital images with no search query
window.onload = function() {
windowResizeEvents();
}
window.onresize = function() {
windowResizeEvents();
}
function windowResizeEvents() {
imagesLoaded();
}
function mosaicCalibration() {
let images = document.querySelectorAll(".mosaic img");
if (window.innerWidth < 750) {
mosaic.classList.add("column");
} else if (window.innerWidth < 1100) {
rowWidth = 2;
} else {
rowWidth = 3 // Math.round(window.innerWidth/(426 + (2/3)));
}
if (window.innerWidth > 750) {
mosaic.classList.remove("column");
for (let i = 0; i < images.length; i++) {
images[i].style.width = `calc((100% - ${((rowWidth - 1) * 1)}rem) / ${rowWidth})`;
}
}
}
function imagesLoaded() {
// Find out row width, image width, etc
mosaicCalibration();
// Remove loader and set height to 0 so new height can be calculated
mosaicLoader.style.display = "none";
mosaic.style.height = 0;
// Define variables
let images = document.querySelectorAll(".mosaic img");
let row = 0;
let rowNum = 0;
let margin = rem(1.25);
let imageWidth = ((mosaic.scrollWidth - (2 * margin)) / rowWidth);
let column = [];
for (let i = 0; i < images.length; i++) {
images[i].style.top = i > rowWidth - 1 ? column[i-rowWidth] + margin : 0;
if (row < rowWidth) {
if (window.innerWidth > 1100) {
images[i].style.left = row * imageWidth + (row >= 1 ? row * margin : 0);
} else {
images[i].style.left = row * imageWidth + (row >= 1 ? (row + 0.5) * margin : 0);
}
row++
} else {
images[i].style.left = 0;
row = 1;
rowNum++;
}
if (rowNum > 0) {
column.push(column[i-rowWidth] + images[i].scrollHeight + margin);
} else {
column.push(images[i].scrollHeight);
}
}
mosaic.style.height = mosaic.scrollHeight;
}

Related

Carousel with dynamic images

Hello I want to implement a carousel in Java Script.
When I launch the page the image loads very strangely and the bootstrap carousel does not work. Do I need to import something to make it work? If I make it static in HTML it works. However the task is to load the images with iiif. Also, there would be way too many images to make it static. Also, I would like to have a filter function implemented which only works dynamically.
Can someone help me how to implement the carousel?
Here is all the JS code:
'import bootstrap.js'
function changeIIIFInformation(iiif, size, quality) {
var index = iiif.indexOf('full')
iiif = iiif.substring(0, index)
iiif += "full/"
iiif += "pct:" +size.toString() +"/"
iiif += "0/"
iiif += quality +".jpg"
return iiif
}
function search_period(period, max_num, offset) {
var count = 0;
var link = ""
var div = document.createElement('div')
var div1 = document.createElement ('div')
var a=document.createElement('a')
var span1=document.createElement('span')
var span2=document.createElement('span')
a.setAttribute('class','carousel-control-prev')
a.setAttribute('href','#carouselExampleControls')
a.setAttribute('role','button')
a.setAttribute('data-slide','prev')
span1.setAttribute('class','carousel-control-prev-icon')
span1.setAttribute('aria-hidden', 'true')
span2.setAttribute('class','sr-only')
span2.innerHTML = 'Previous'
div.setAttribute('class', 'carousel slide')
div.setAttribute('data-ride', 'carousel')
div.setAttribute('id', 'carouselExampleControls')
div1.setAttribute('class','carousel-inner')
var h2 = document.createElement('h2')
var iiif = ""
h2.innerHTML = period
document.body.appendChild(h2)
const keys = Object.keys(urls);
for(const elem of keys) {
var label = urls[elem].label
for(const el of urls[elem].variants) {
if(el.label.includes('front')) {
iiif = el.url
}
}
if(!periods.hasOwnProperty(label)) {
continue;
}
if(periods[label] != period) {
continue;
}
if(count < offset) {
count+=1
continue
}
var div2= document.createElement ('div')
div2.setAttribute('class','carousel-item active')
link = changeIIIFInformation(iiif, 10, "default")
var figure = document.createElement('figure')
var figcaption = document.createElement('figcaption')
var linkToImage = document.createElement('a')
//linkToImage.setAttribute('#image', label)
linkToImage.setAttribute('href', 'annotator#'+label)
linkToImage.innerHTML = label
figcaption.appendChild(linkToImage)
var image = document.createElement('img')
image.setAttribute("id", "myimg");
image.setAttribute('src', link)
image.setAttribute('class','d-block w-100')
// figure.appendChild(image)
// figure.appendChild(figcaption)
div.appendChild(div1)
div.appendChild(a)
div1.appendChild(div2)
a.appendChild(span1)
a.appendChild(span2)
div2.appendChild(image)
figure.setAttribute("id", "myFigure");
count += 1;
if(count >= max_num+offset) {
break;
}
}
document.body.appendChild(div)
}
function clear_dom() {
var elements = document.getElementsByTagName('div')
var headings = document.getElementsByTagName('h2')
var buttons = document.getElementsByTagName('button')
while(buttons.length > 0) {
buttons.item(0).remove()
}
while(elements.length > 0) {
elements.item(0).remove()
}
while(headings.length > 0) {
headings.item(0).remove()
}
}
function show_initial_load() {
search_period('Ur III (ca. 2100-2000 BC)', )
}
function show_filtered(selected, offset) {
clear_dom()
search_period(selected, 10, offset)
var previous = document.createElement('button')
if(offset-10 < 0) {
previous.onclick = () => show_filtered(selected, 0)
} else {
previous.onclick = () => show_filtered(selected, offset-10)
}
previous.innerHTML = 'Previous'
document.body.appendChild(previous)
var next = document.createElement('button')
next.onclick = () => show_filtered(selected, offset+10)
next.innerHTML = 'More'
document.body.appendChild(next)
}
function update_view() {
var selected = document.getElementById('perriod-select').value
clear_dom()
if(selected == '') {
show_initial_load()
} else {
show_filtered(selected, 0)
}
}

Processes for optimizing canvas animations

I've got a small web app in development to simulate the Ising model of magnetism. I've found that the animation slows down considerably after a few seconds of running, and it also doesn't loop after 5 seconds like I want it to with the command:
setInteval(main, 500)
I've added start and stop buttons. When I stop the animation, and then restart it, it begins fresh at the usual speed, but again slows down.
My question is: what steps can I take to troubleshoot and optimize the performance of my canvas animation? I hope to reduce or mitigate this slowing effect.
JS code:
window.onload = function() {
var canvas = document.getElementById("theCanvas");
var context = canvas.getContext("2d");
var clength = 100;
var temperature = 2.1;
var playAnim = true;
canvas.width = clength;
canvas.height = clength;
var imageData = context.createImageData(clength, clength);
document.getElementById("stop").addEventListener("click",function(){playAnim=false;});
document.getElementById("start").addEventListener("click",function(){playAnim=true;});
function init2DArray(xlen, ylen, factoryFn) {
//generates a 2D array of xlen X ylen, filling each element with values defined by factoryFn, if called.
var ret = []
for (var x = 0; x < xlen; x++) {
ret[x] = []
for (var y = 0; y < ylen; y++) {
ret[x][y] = factoryFn(x, y)
}
}
return ret;
}
function createImage(array, ilen, jlen) {
for (var i = 0; i < ilen; i++) {
for (var j = 0; j < jlen; j++) {
var pixelIndex = (j * ilen + i) * 4;
if (array[i][j] == 1) {
imageData.data[pixelIndex] = 0; //r
imageData.data[pixelIndex+1] = 0; //g
imageData.data[pixelIndex+2] = 0; //b
imageData.data[pixelIndex+3] = 255; //alpha (255 is fully visible)
//black
} else if (array[i][j] == -1) {
imageData.data[pixelIndex] = 255; //r
imageData.data[pixelIndex+1] = 255; //g
imageData.data[pixelIndex+2] = 255; //b
imageData.data[pixelIndex+3] = 255; //alpha (255 is fully visible)
//white
}
}
}
}
function dU(i, j, array, length) {
var m = length-1;
//periodic boundary conditions
if (i == 0) { //top row
var top = array[m][j];
} else {
var top = array[i-1][j];
}
if (i == m) { //bottom row
var bottom = array[0][j];
} else {
var bottom = array[i+1][j];
}
if (j == 0) { //first in row (left)
var left = array[i][m];
} else {
var left = array[i][j-1];
}
if (j == m) { //last in row (right)
var right = array[i][0];
} else {
var right = array[i][j+1]
}
return 2.0*array[i][j]*(top+bottom+left+right); //local magnetization
}
function randInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
var myArray = init2DArray(clength, clength, function() {var c=[-1,1]; return c[Math.floor(Math.random()*2)]}); //creates a 2D square array populated with -1 and 1
function main(frame) {
if (!playAnim){return;} // stops
window.requestAnimationFrame(main);
createImage(myArray, clength, clength);
context.clearRect(0,0,clength,clength);
context.beginPath();
context.putImageData(imageData,0,0);
for (var z = 0; z < 10*Math.pow(clength,2); z++) {
i = randInt(clength-1);
j = randInt(clength-1);
var deltaU = dU(i, j, myArray, clength);
if (deltaU <= 0) {
myArray[i][j] = -myArray[i][j];
} else {
if (Math.random() < Math.exp(-deltaU/temperature)) {
myArray[i][j] = -myArray[i][j];
}
}
}
}
var timer = setInterval(main, 500);
}

jQuery animate scrollLeft stops working after several clicks in FF and Chrome (but not Safari)

I have a very strange problem with some jquery code that scrolls a group of images. It seems to work in all browsers for the first several clicks, advancing the images by a number. And in Safari, it will work perfectly all the way to the end of the slideshow. But in FF and Chrome it will stop after a certain number of images. And this number is NOT always the same for some reason.
For example, on this page FF/Chrome will stop after clicking the next arrow 7 times.
And on this page, FF/Chrome will stop after clicking the next arrow 6 times.
Yet on this page, FF/Chrome will work all the way to the end as expected (and as Safari does all the time).
This is the code that controls the clicking:
<script>$(window).load(function(){
var currentElement = $("#ngg-gallery-list > div:nth-child(2)");
var onScroll = function () {
//get the current element
var container = $("#ngg-galleryoverview");
var wrapper = $("#ngg-gallery-list");
var children = wrapper.children();
var position = 0;
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
var childLeft = container.offset().left < child.offset().left;
if (childLeft) {
currentElement = child;
return;
}
}
}
var scrollToElement = function ($element) {
var container = $("#ngg-galleryoverview");
var wrapper = $("#ngg-gallery-list");
var children = wrapper.children();
var width = 0;
console.log(children.length);
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
if (child.get(0) == $element.get(0)) {
if (i == 0) {
width = 300;
}
container.animate({
scrollLeft: width
}, 300);
onScroll();
}
if (child.next().length > 0) {
//make sure we factor in borders/padding/margin in height
width += child.next().offset().left - child.offset().left
} else {
width += child.width();
}
}
}
var next = function(event) {
event.preventDefault();
scrollToElement(currentElement);
}
var prev = function(event) {
event.preventDefault();
var container = $("#ngg-galleryoverview");
if (currentElement.prev().length > 0) {
if (container.offset().left == currentElement.prev().offset().left) {
currentElement = currentElement.prev().prev().length > 0 ? currentElement.prev().prev() : currentElement.prev();
} else {
currentElement = currentElement.prev();
}
}
scrollToElement(currentElement);
}
$("#ngg-galleryoverview").on('scroll', onScroll);
$("#nexty").click(next);
$("#prevy").click(prev);
});
</script>
I'm stumped.
Well, making my code look more like what I found here fixed the problem. (Even if I am not entirely sure why). Hoping it helps someone else, here is the final code:
<script>
$(document).ready(function () {
var currentElement = $("#ngg-galleryoverview > div:nth-child(1)");
var onScroll = function () {
var container = $("#ngg-galleryoverview");
var children = $(".list");
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
var childLeft = container.offset().left < child.offset().left;
if (childLeft) {
currentElement = child;
//console.log(currentElement);
return;
}
}
};
var scrollToElement = function ($element) {
var container = $("#ngg-galleryoverview");
var children = $(".list");
var width = 0;
for (var i = 0; i < children.length; i++) {
var child = $(children[i]);
if (child.get(0) == $element.get(0)) {
if (i === 0) {
width = 0;
}
container.animate({
scrollLeft: width
}, 500);
onScroll();
}
if (child.next().length > 0) {
width += child.next().offset().left - child.offset().left;
} else {
width += child.width();
}
}
};
var buttonright = function (e) {
scrollToElement(currentElement.next());
};
var buttonleft = function (e) {
var container = $("#ngg-galleryoverview");
if (currentElement.prev().length > 0) {
if (container.offset().left == currentElement.prev().offset().left) {
currentElement = currentElement.prev().prev().length > 0 ? currentElement.prev().prev() : currentElement.prev();
} else {
currentElement = currentElement.prev();
}
}
scrollToElement(currentElement);
};
onScroll();
$("#ngg-galleryoverview").scroll(onScroll);
$("#nexty").click(buttonright);
$("#prevy").click(buttonleft);
});</script>

JavaScript increase and decrease font size

I am new to JavaScript. I would like to add to add two buttons for my visitors to control font size. I would like to include two tags - 'p' and 'blockquote". Can you please help me edit this code in order to include both?
var min = 8;
var max = 18;
function increaseFontSize() {
var p = document.getElementsByTagName('p');
for (i = 0; i < p.length; i++) {
if (p[i].style.fontSize) {
var s = parseInt(p[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
p[i].style.fontSize = s + "px"
}
}
function decreaseFontSize() {
var p = document.getElementsByTagName('p');
for (i = 0; i < p.length; i++) {
if (p[i].style.fontSize) {
var s = parseInt(p[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != min) {
s -= 1;
}
p[i].style.fontSize = s + "px"
}
}
Thank you.
Here's a working version:
http://jsfiddle.net/ny4p7pg9/
I took the liberty of refactoring a bit the functions to make the code more parameterized.
function changeFontSize(delta) {
var tags = document.querySelectorAll('p,blockquote');
for (i = 0; i < tags.length; i++) {
if (tags[i].style.fontSize) {
var s = parseInt(tags[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += delta;
}
tags[i].style.fontSize = s + "px"
}
}
function increaseFontSize() {
changeFontSize(1);
}
function decreaseFontSize() {
changeFontSize(-1);
}
Instead of using:
p = document.getElementsByTagName('p');
you could, instead use:
elems = document.querySelectorAll('p, blockquote');
(the variable name is irrelevant, and was changed only because the elements are no longer exclusively <p> elements):
function increaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
elems[i].style.fontSize = s + "px"
}
}
var min = 8;
var max = 18;
function increaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != max) {
s += 1;
}
elems[i].style.fontSize = s + "px"
}
}
function decreaseFontSize() {
var elems = document.querySelectorAll('p, blockquote');
for (i = 0; i < elems.length; i++) {
if (elems[i].style.fontSize) {
var s = parseInt(elems[i].style.fontSize.replace("px", ""));
} else {
var s = 12;
} if (s != min) {
s -= 1;
}
elems[i].style.fontSize = s + "px"
}
}
document.querySelector('#increase').addEventListener('click', increaseFontSize);
document.querySelector('#decrease').addEventListener('click', decreaseFontSize);
<button id="increase">↑A</button>
<button id="decrease">A↓</button>
<p>Some text to have its text adjusted by the buttons just up there.</p>
<blockquote>Some text in a blockquote</blockquote>
The querySelectorAll() method accepts CSS-style selectors, and returns a (non-live) NodeList, and is supported in all modern browsers, including IE from version 8 onwards.
That said, it's probably better to increase the font-size of the <body> element, otherwise font-adjustment is redundant (since other elements will still be unclear), so, instead, I'd suggest:
function increaseFontSize() {
// retrieving, and caching, the <body> element:
var body = document.body,
// finding the current computed fontSize of the <body> element, parsing it
// as a float (though parseInt() would be just as safe, really):
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
// if the currentFontSize is less than the specified max:
if (currentFontSize < max) {
// we set the fontSize of the <body> to the incremented fontSize,
// increasing the current value by 1, and concatenating with the 'px' unit:
body.style.fontSize = ++currentFontSize + 'px';
}
}
function decreaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize > min) {
body.style.fontSize = --currentFontSize + 'px';
}
}
var min = 8;
var max = 18;
function increaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize < max) {
body.style.fontSize = ++currentFontSize + 'px';
}
}
function decreaseFontSize() {
var body = document.body,
currentFontSize = parseFloat(window.getComputedStyle(body, null).fontSize);
if (currentFontSize > min) {
body.style.fontSize = --currentFontSize + 'px';
}
}
document.querySelector('#increase').addEventListener('click', increaseFontSize);
document.querySelector('#decrease').addEventListener('click', decreaseFontSize);
<button id="increase">↑A</button>
<button id="decrease">A↓</button>
<p>Some text to have its text adjusted by the buttons just up there.</p>
<blockquote>Some text in a blockquote</blockquote>
References:
document.body.
document.querySelectorAll().
Window.getComputedStyle().

Large list rendering in JavaScript

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%;
}

Categories