adding divs and clearing container repeatedly makes memory grow - javascript

I have a simple test page where I have a container.
<div id="canvas"></div>
Once the page is ready I create an interval of 1 second where canvas is emptied, 3000 divs are created and appended to the canvas.
var id = 0;
var canvas;
$(document).ready(function(){
canvas = $("#canvas");
addElements();
});
function addElement(){
for(var i= 0 ; i < 3000; i++){
var html = "<div class=\"element\" id='div_id"+ id + "'>" + id + "</div>";
canvas.append(html);
id++;
}
}
function addElements(){
addElement();
setInterval(function(){
//canvas.empty();
canvas.find("*").off();
canvas.children().remove();
},1000);
}
Any ideas on why the memory keeps growing like 3MB every second?
Here is a sample Plunkr
Thanks in advance

Related

Vanilla Javascript: Infinite Image Marquee

Okay so I must create an infinite auto-scrolling horizontal image marquee using vanilla JS. I have the following code:
//if(painkiller<14){painkiller++;} else{painkiller=0;backup2()}
var speed = 5;
var exeggcute = true;
var painkiller = 0;
var marquix = document.getElementById("marquis");
var backup = "";
var coquus = 0;
for (var painkiller = 0; painkiller < 15; painkiller++) {
backup += "<img class='slide' src='" + ImgArray[painkiller].src + "' width='" + ImgArray[painkiller].width + "'>";
}
marquix.innerHTML = backup;
function riverflow() {
marquix.scrollLeft += 5;
if (marquix.children[0].getBoundingClientRect().left <= (marquix.children[0].width * -1)) {
marquix.appendChild(marquix.children[0]);
//marquix.getBoundingClientRect().left=0;
//marquix.children[0].style.transform="translateX(133px)"
}
}
//function backup2(){marquix.innerHTML=backup;}
setInterval('riverflow()', 50);
exeggcute = true;
<head>
<script>
var ImgArray = [];
for (var i = 0; i < 15; i++) {
ImgArray[i] = new Image();
ImgArray[i].src = "imgx/imagen" + (i + 1) + ".jpg";
ImgArray[i].width = 133;
}
</script>
</head>
<body>
<div id="marquis">
</div>
</body>
Basically I'm creating the image chain, then filling with it the innerHTML of a div, then assigning said div to a variable, and finally calling a repetitive function through setInterval(). Now, what that function does is a simple scroll to the left and - when the first image is completely out of the viewport - use appendChild to rip the first child element or img from the image chain then put it at the end of it. So no image overcharge is produced and the marquee uses the same 15 element once and again.
Here's my problem, though: when the appendChild function fires, the image that's out of the viewport is removed, however, the next image in line - as well as the rest of the chain - does not preserve its current position, and is instead forcefully scrolled to fill the gap left by the then-first image that's now at the end. Thus, the condition of the appendChild (which was the first children of the div being completely out of the viewport) becomes true and activates the function - leading the whole marquee to slide non-stop and out of control, as the appendChild is firing continuously.
How can I fix it?
Possible solutions:
You will need to reset the scrollLeft to 0 on the same moment that you switch the images.
You will need to add some element (another img for example at the begining) it could be all white or transparent. That image will be always there, before the firstone visible. When you remove the other image this auxiliar image need to be wider (change the width) to fill the gap, so add to its width the width of the removed image each time you remove one.
Or you can change the marginLeft of the leftmost image with marquix.children[0].style.marginLeft = n + "px";
That's what I came up with, but as I said, the translateX() parameter increases ad infinitum.
<script>
var ImgArray=[];
for (var i=0; i<15; i++){
ImgArray[i]= new Image();
ImgArray[i].src= "imgx/imagen"+(i+1)+".jpg";
ImgArray[i].width=133;
}
</script>
</head>
<body>
<div id="marquis">
<script>
//if(painkiller<14){painkiller++;} else{painkiller=0;backup2()}
var exeggcute= true;
var painkiller=0;
var marquix = document.getElementById("marquis");
var backup=""; var coquus=0;
for(var painkiller =0;painkiller<15;painkiller++){
backup+="<img class='slide' src='"+ImgArray[painkiller].src+"' width='"+ImgArray[painkiller].width+"'>";
}
marquix.innerHTML=backup;
var slidin=133;
function riverflow(){
marquix.scrollLeft+=10;
if (marquix.children[0].getBoundingClientRect().left<=(marquix.children[0].width*-1) && exeggcute){
marquix.appendChild(marquix.children[0]);
marquix.getBoundingClientRect().left=0;
for (var j=0; j<15; j++){
marquix.children[j].setAttribute("style","transform: translateX("+slidin+"px)")
}
slidin+=133;
}
}
//function backup2(){marquix.innerHTML=backup;}
setInterval('riverflow()',50);
exeggcute=true;
</script>

Using Json to load all images from server, and displaying them Masonry

What I'm trying to do is get 20 or so images from a folder on the server and display them using masonry.desandro and once scrolled to the bottom it will load another set of 20 images. Just like pinterest.
Currently it does load the images 20 at a time, the only problem I'm having is the first 20 display Masonry but when the next 20 load they aren't displaying Masonry
HTML
<div class="grid">
</div>
Json
$(document).ready(function() {
// The max number of images to be loaded at a time.
var limit = 16;
// JSON data will be assigned to this
var images = "";
// to remember where in JSON we are
// initialize to the value of limit - so that we can load in images
// before page scroll.
var currentIndex = limit;
// When there are fewer than `limit` images left, this
// value will be the difference between the current index
// and the length of the images array.
var stop = limit;
var grid = $(".grid");
// Make a GET request to the api
$.getJSON("***********************/newsite/api.php", function(data) {
// save the data to be used later.
images = data.weddingCakes;
console.log(data);
})
// create the first round of images.
.done(function() {
var html = "";
for (var i = 0; i < limit; i++) {
html += '<div class="grid-item"><img src="' + images[i] + '"></div>';
}
grid.append(html)
.masonry({
gutter: 3,
itemSelector: '.grid-item',
animate: true
});
console.log("masonry")
})
.error(function() {
console.log("error");
});
$(document).scroll(function() {
// get the scoll position with support for IE
// see http://jsbin.com/egegu3/6/edit?html,js,output
// for original code.
var totalHeight, currentScroll, visibleHeight;
if (document.documentElement.scrollTop) {
currentScroll = document.documentElement.scrollTop;
} else {
currentScroll = document.body.scrollTop;
}
totalHeight = document.body.offsetHeight;
visibleHeight = document.documentElement.clientHeight;
// only load more images if the scroll bar is at the bottom
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
var diff = images.length - currentIndex;
// if the difference is > 0 then there are more images in the array
if (diff > 0) {
stop = diff > limit ? limit : diff;
getImages(currentIndex, stop);
currentIndex += stop;
}
// otherwise, reset the index before calling getImages()
else {
currentIndex = 0;
stop = diff > limit ? limit : diff;
getImages(currentIndex, stop);
currentIndex += stop;
}
}
});
});
// gets the path for each image from index to stop
function getImages(index, stop) {
var html = "";
// create the img tags.
for (var i = index; i < index + stop; i++) {
html += '<div class="grid-item"><img src="' + images[i] + '"></div>';
}
var str = $(html);
grid.append(html).masonry("appended", str);
}
});
My JSfiddle
you were almost correct just missed a small part while reading documentation, here while appending elements you need to append HTML elements and pass same to the masonry function.
You were adding string to append and later on you were passing element to the masonry, Also this code -> var str = $(html); returns Array of HTML elements rather than string, so you need to add these elements to the grid and pass it to masonry
so your little change would be...
// gets the path for each image from index to stop
function getImages(index, stop) {
var html = "";
// create the img tags.
for (var i = index; i < index + stop; i++) {
html += '<div class="grid-item"><img src="' + images[i] + '"></div>';
}
var str = $(html);
grid.append(str).masonry("appended", str); // This line is a change
}
I have dummy fiddle for this as well

Image gallery issue jquery

While I'm creating image gallery dynamically it isn't working. Here I'm adding all the images from a directory to a table dynamically. Its not completed now.
Here, I want to create image gallery dynamically and I'm new to jquery. see the partial code below.
sorry. The issue is image gallery is not working. while i clicking on a image it is going to displayed in another page.
in html,
<table id="tbl1">
</table>
in js,
<script type="text/javascript">
$(document).ready(function() {
var bss = $('a[rel=blogslideshow]').bsShow({
effect: 'Ladder',
direction: 'horizontal'
});
var arr1 = ["sample_fussen.jpg", "sample_zakopane.jpg", "sample_wurzburg.jpg", "sample_keukenhof.jpg"];
var cnt = 0;
var festname = "slides";
alert(arr1.length);
var rows = arr1.length / 5; //here's your number of rows and columns
var cols = 5;
for (var r = 0; r < rows; r++) {
var tr = $('<tr>');
for (var c = 0; c < cols; c++) {
if (cnt == arr1.length)
break;
var path = festname + '/' + arr1[cnt];
$("<td><img src="
"+path+"
" width="
100 " height="
100 " alt="
"/><h3><label><input type="
radio " name="
radio1 " value="
">Select Image</label></h3></td>").appendTo(tr);
cnt++;
}
$('#tbl1').last().after(tr);
}
table.appendTo('body');
})
</script>
I'm using reference link.
https://code.google.com/p/blogslideshow/downloads/list
First, you are trying to initialize the anchor tag which you are not adding in table. Second, you are initializing your plugin before appending to body which never works because it is not present in DOM.
So try to add anchor tag in td and wrap your image to anchor tag like,
$("<td><a rel='blogslideshow' title='Your title' href='"+path+"'><img src='"+path+"' width='100'"+
"height='100' alt=''/></a>"+
"<h3><label><input type='radio'"+
"name='radio1' value=''>Select Image</label>"+
"</h3></td>").appendTo(tr);
after appending the data you need to re-initialize your plugin
var bss = $('a[rel=blogslideshow]').bsShow({
effect: 'Ladder',
direction: 'horizontal'
});
Live Demo

Add html code to a dynamically generated div

I have a js question that annoys me for the last couple of days.
i have a parallax template, where the parallax elements are generated automatically from js file.So i can add css style like transitions etc., but i would like to add some links on top of the divs, or some kind of on clik events.
What i think i have to look so far is in this fille (where the id of the divs are created):
enter //Parallax Element 2
var item = {};
item.name = "#tree21";
item.stackOrder = 1;
item.content = "image";
item.image = "images/parallax/bg2.png";
item.sizes = {w:"350",h:"350"};
item.screenPos = ["40%","-100%","300%","-115%"];
item.visibility = ["true","true","true","true"];
item.parallaxScene = true;
item.bPos = 200;
item.mouseSpeed = 15;
items.push(item);
and here (where i think the divs are generated
createScenes: function () {
//Resize Parallax Elements if responsive
if (responsive) {
var screenProp = this.maxWidth / 1920;
} else {
var screenProp = 1;
}
for (var i = 0; i < items.length; i++) {
if (jQuery(items[i].name).length == 0) {
jQuery("#parallax-container").append("<div id='" + items[i].name.substring(1, (items[i].name.length)) + "' class='parallaxItem'></div>");
}
Thank you!
Store a reference to your new div:
var div = jQuery("<div id='"
+ items[i].name.substring(1, (items[i].name.length))
+ "' class='parallaxItem'></div>")
.appendTo(jQuery("#parallax-container"));
jQuery(div).append('...');

Without using jquery, how to cycle through images to make a simple slideshow

You have a div, with 3 images in it.
How to create a simple slideshow that cycles through the images, and displays each image for 5 seconds and goes back to the first image when done and continues looping.
Without using jquery or any other framework.
(function () {
var imgs = document.getElementById('your_div').getElementsByTagName('img'),
index = 0;
imgs[0].style.display = 'block';
setInterval(function () {
imgs[index].style.display = 'none';
index = (index + 1) % imgs.length;
imgs[index].style.display = 'block';
}, 5000);
}());
Example HTML: http://jsfiddle.net/Zq7KB/1/
Edit: Saw a more elegant example above that used .length.
You can use setInterval to set up the timed callback, and set the src of an img element:
window.onload = function() {
var slides = [ "path_to_image_one",
"path_to_image_two",
"path_to_image_three" // ...
],
index = 0,
timer = 0;
// Show the first slide
showNextSlide();
// Show "next" slide every five seconds
timer = setInterval(showNextSlide, 5000);
// The function we call to show the "next" slide
function showNextSlide() {
if (index >= slides.length) {
index = 0;
}
document.getElementById('theImage').src = slides[index++];
}
};
...where your markup for the image is:
<img id="theImage" src="path_to_initial_placeholder">
Note that I've stored the timer handle in timer but not used it. This is just because you might use it to cancel the timer if you need to stop the slideshow.
Update: Just saw that you want to get the images from a div somewhere (whereas above I've supplied the paths in the code itself). Simple enough to create slides dynamically; revised edition of the above that grabs the images that are direct children of the div with the ID "theDiv":
window.onload = function() {
var slides = [],
index = 0,
timer = 0,
node;
// Get the slides
for (node = document.getElementById('theDiv').childNodes;
node;
node = node.nextSibling) {
if (node.nodeType == 1 && node.tagName == "IMG") {
slides.push(node.src);
}
}
// Show the first slide
showNextSlide();
// Show "next" slide every five seconds
timer = setInterval(showNextSlide, 5000);
// The function we call to show the "next" slide
function showNextSlide() {
if (index >= slides.length) {
index = 0;
}
document.getElementById('theImage').src = slides[index++];
}
};
Well you'd have to get a handle for the <div> first, so if it has an "id" value:
var theDiv = document.getElementById("imgContainer");
Now you just have to set up a timer to cycle through the images:
(function(div, sleep) {
var idx = 0;
var imgs = div.getElementsByTagName('img');
function showOne() {
for (var i = 0; i < imgs.length; ++i)
imgs[i].style.display = 'none';
imgs[idx].style.display = '';
idx = (idx + 1) % imgs.length;
setTimeout(showOne, sleep);
}
showOne();
})(theDiv, 5000);
var image = new Array('/img/1.jpg', '/img/2.jpg', '/img/3.jpg');
setTimeout("show_next()",5000);
function show_next()
{
var container = document.getElementById('image_container');
container.innerHTML = "<img src='" + image[i] + "' />";
if(i==2) { i = 1; }else { i = i + 1; }
}
I thought this was a nice simple answer, but there were a couple of errors.
setInterval rather than setTimeout and the initial index was not set. I also amended to load first image immediately.
var image = new Array('imgs/18/P1050294-XL.jpg', 'imgs/18/P1050293-XL.jpg', 'imgs/18/P1040984-XL.jpg', 'imgs/18/P1040983-XL.jpg', 'imgs/18/P1040982-XL.jpg');
var path = 'mypath';
document.getElementById('slideShow').innerHTML = "<img width='600px' src='" + path + image[0] + "' />" // Load First image
var i = 1; // Set counter to second image, for first use of loop
setInterval("show_next(path)",5000);
function show_next(path)
{
var container = document.getElementById('slideShow');
container.innerHTML = "<img width='600px' src='" + path + image[i] + "' />";
if(i==4) { i = 0; } else { i = i + 1; }
}

Categories