Javascript native .remove() does not work on HTMLCollection. Javascript Bug? - javascript

I'm simply trying to iterate through an HTMLCollection (images inside a div) with a simple for loop. I use the children() method to get the images, and the item() method to get the specific image. Although the console shows me each image element (that I am logging), using remove() on each element isn't working. It does not remove all images.
I've tried using array indexes, removeChild() method, but it's the same problem: so I guess the problem lies on the HTMLCollection capacity?
var imgs = document.getElementByID('box').children;
for (var i = 0; i < imgs.length; i++) {
var e = imgs.item(i);
console.log(e)
document.getElementByID('box').removeChild(e)
}
}
HTML markup:
<div id="box">
<img src="images/1.jpg" alt="">
<img src="images/2.jpg" alt="">
<img src="images/3.jpg" alt="">
</div>
I expect that every element will be removed from #box, but the second image element stays in place. I don't really grasp why.

HTMLCollection is not an array, it is a live list of DOM elements. Therefore your loop goes like this:
1st round:
imgs = 1.jpg, 2.jpg, 3.jpg
removeChild(imgs[0]) removes 1.jpg
2nd round:
imgs = 2.jpg, 3.jpg
removeChild(imgs[1]) removes 3.jpg
3rd round:
imgs = 2.jpg
removeChild(imgs[2]) removes undefined, does nothing
The simple fix is to loop through the array in reverse:
for (var i = imgs.length-1; i >= 0; i--) ...

I would loop through all childNodes of the div[id="box"] and remove them accordingly.
Check out the code sample:
document.querySelectorAll('#box img')
.forEach(node => {
// do some additional checks, if needed
node.remove();
});
<div id="box">
<img src="images/1.jpg" alt="">
<img src="images/2.jpg" alt="">
<img src="images/3.jpg" alt="">
</div>

You are using removeChild(), not remove().
A solution to your problem would be this:
let imgs = document.getElementById('box').children();
imgs.forEach(img => img.remove());

The first problem you have is document.getElementByID - the correct method is .getElementById - lowercase d in the end.
Second, your loop will miss some elements. If you do a for loop and start removing elements, then the length of the collection also changes. What happens (in pseudo representation):
loop start
index = 0;
collection = [1, 2, 3];
remove item 0;
index = 1;
collection = [2, 3];
remove item 1;
index = 2;
collection = [2];
remove item 3; //error
You can loop in reverse from the end to the beginning but it's easier to use forEach which guarantees you go over each element in the initial array:
document.getElementById("remove").addEventListener("click", removeImages)
function removeImages() {
var imgs = document.getElementById('box').children;
[...imgs].forEach(img => img.remove());
}
<div id="box">
<img src="images/1.jpg" alt="">
<img src="images/2.jpg" alt="">
<img src="images/3.jpg" alt="">
</div>
<button id="remove">Remove all</button>

Related

Target by ID elements in array assigned by get() jQuery

Apologies if I get the terminology wrong here.
I have a 'grid' of images in html that I want to use jQuery to fade in each element randomly. One item in the grid is a Logo - I want it to fade in last. The grid size could be changed and the position of the 'logo' could also be different. Here is a reduced simplified output of the list.
<ul id="homepage-grid" class="projectsgrid row">
<div id="item1">
</div>
<div id="item2">
</div>
<div id="itemlogo" style="opacity: 0;">
<a href="#" class="block" style="padding-bottom: 100%;">
<div style="background-image:url('logoonly.png')" title="" class="logoblock"></div>
</a>
</div>
<div id="item4">
</div>
<div id="item5">
</div>
</ul>
I have the following script which will collect the elements into an array.
But i can't figure out how to match the element with the 'itemlogo' ID in the collection to split it out and push it to the end of the array so it is last to 'fade in'. I have tried "div#itemlogo", "#itemlogo", "itemlogo" but nothing seems to match, and perhaps not knowing the name of what I am doing I can't find any references.
var elems = $('#homepage-grid > div').get(); // collect elements
console.log(elems);
for (var i = elems.length - 1; i > 1; i--) { // Shuffle the order
var j = Math.floor(Math.random() * (i + 1));
var elem = elems[j];
elems[j] = elems[i];
elems[i] = elem;
}
elms = elems.push(elems.splice(elems.indexOf('div#itemlogo'), 1)[0]); // pull logo to last??
var i = 0;
var timer = setInterval(function() { // animate fade them sequentially
console.log(elems[i]).id();
$(elems[i]).fadeTo( "slow" , 1);
if (i === elems.length) {
clearInterval(timer);
}
i++;
}, 150);
You're on the right path, but the key here is that you need to find a particular item. Those items are DOM elements, not strings or selectors on their own.
elems.push(
elems.splice(
elems.findIndex(node=>node.id === 'itemlogo'),
1
)[0]
);
findIndex allows you to pass a function that should return true for the item you want - in this case, you want the item whose ID is itemlogo. The rest is just the same push-splice thing you have already.
I would also like to praise your correct use of array shuffling. You can simplify it a little bit with destructuring:
[elems[i], elems[j]] = [elems[j], elems[i]];

Parse image from json string

I need to get all my images (for futher converting to canvas) from plain json string...
For example i can have in json string:
<p>someText</p>
<img src="">
or
asdasdasasd
asdasdasd
asd <img class="asd" src="123">
and i use it so:
var html = $.parseHTML(someString)
**
.children('img')
.find('img')
but those functions didn't work(
How can i get all my img objects from this html? So, that i can further use it with drawImage (canvas)
is it possible?
upd
via ajax i get, for example, such data:
<p>someText</p>
<img src="">
or
asdasdasasd
asdasdasd
asd <img class="asd" src="123">
or
<h3><p>someText <img src=""></p><h3>
etc...
and somehow i need to convert this string to a 'virtual' DOM, where i can get images (and other elements too) and manipulate with them with jQuery. Like i can fetch images for my window-object: $('img') - this will fetch all images from page body. And i need something similar for my string. So, that i can use this images with jQuery.
You are getting an array after the parseHTML function. I think, you should traverse it and look that if it is an image, get it and add $(array_element).
After this process, you will get a Jquery object that can use attr(), find() etc. functions.
var k = '<p>sosmeT22ext2</p><img class="c" src="empty"><img class="empty" src="123">';
var html = $.parseHTML(k);
for(var i = 0; i < html.length; i++){
if(html[i] instanceof HTMLImageElement){
console.log($(html[i]).attr("src")); // all jquery functions works on $(html[i])
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Update
Above code doesn't work in nested dom html. Because it just traverse in one level as you see. Below code is more complicated beacuse it is a recursive method. My suggestion is that, if your dom is not nested use the first code block, it is not use the recursive method to extract and use your images.
var k = '<div><p>s133o4s3meT232ext2</p><img class="c" src="empty"><img class="empty" src="123"></div>';
var html = $.parseHTML(k);
var images_arr = [];
get_child_nodes(html);
console.log(images_arr[1].attr("src"));
function get_child_nodes(html_l){
for(var i = 0; i < html_l.length; i++){
if(html_l[i] instanceof HTMLImageElement){
images_arr.push($(html_l[i]));
}
else {
for(var j = 0; j < html_l[i].childNodes.length; j++){
get_child_nodes($(html_l[i].childNodes[j]));
}
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Adding to my comment, found the actual solution for your Problem:
> $('<p>someText</p><img src="">').filter('img')
[img]
The problem is that your HTML does not have a child which can be an img, but one of the root elements is, filter takes the root elements into account.
Compare (bad/worse but finds nested):
> $('<div><p>someText</p><img src=""></div>').find('img')
> $('<div></div>').append($('<p>someText</p><img src="">')).find('img')
Solution that always works, combining the selectors find and filter without creating an extra root element:
> $('<p>someText</p><img src=""><div><img></div>').filter('img')
[img]
> $('<p>someText</p><img src=""><div><img></div>').find('img')
[img]
> h = $('<p>someText</p><img src=""><div><img></div>')
[p, img, div]
> h.find('img').add(h.filter('img'))
[img, img]

How to change the order of HTML element (images) onclick

I'm beginner in HTML/SCC/JC and I try to solve by myself. But this one have too much of my time and I decided to ask for help. To tell the truth I chaked for answerd in the internet)
I need to change the order of images by click on the buttom, how to do this?
JS: function change_order() { } ???
<div id="container">
<div id="one">
<input id="b1" value="Change the image order" onclick="change_order()" type="button"/>
<h1 style="font-size: 12"> Header HeaderHeaderHeader</h1>
<p style="font-size:8"> text text text </p>
</div>
<div id="two">
<img id="pict_01" src="https://www.khanacademy.org/images/topic-icons/math/doodling-in-math.png?v2" />
<img id="pict_02" src="http://www.milldamschool.ik.org/img/d666f5fc-db14-11de-a689-0014220c8f46-5812526.jpg" />
<img id="pict_03" src="http://www.birdsontheblog.co.uk/wp-content/uploads/2010/05/maths.jpg" />
</div>
</div>
In CSS I placed the columns and images (static position).
Actually I'm not sure about onclick buttum if it's conneted to JS.
Full code here http://jsfiddle.net/SantaUA/ovcheyfa/
This should get you on the right lines
$('img').on("click", function() {
$(this).insertBefore( $(this).prev('img') );
});
Here is a JSFIDDLE
Hope this helps
It is very easy. You will need to get the id of the element in javascript, the picture in this case and change its source or src.
So create something like this
var firstpic = document.getElementById("pict_01");
firstpic.src = "secondpicture.jpg";
The previous code will put the second image in your first image. Just repeat the following code for all pictures and you will achieve what u asked for.
Hope this helped
Basically what you want to do is put all the images into an array and then shuffle the order of the array. After you change the order of the array, you can output the new array back out to the screen.
I've put together an example to show you how to do this correctly using jQuery. The following sample will shuffle your images randomly every time you push the Shuffle Me button.
Note that I changed the name of your div from id="two" to id="picContainer".
HTML:
<div id="picContainer">
<img id="pict_01" src="https://www.khanacademy.org/images/topic-icons/math/doodling-in-math.png?v2" />
<img id="pict_02" src="http://www.milldamschool.ik.org/img/d666f5fc-db14-11de-a689-0014220c8f46-5812526.jpg" />
<img id="pict_03" src="http://www.birdsontheblog.co.uk/wp-content/uploads/2010/05/maths.jpg" />
</div>
JS (jQuery):
//grab the div that contains our images
var container = $('#picContainer');
//grab our button
var button = $('.shuffleMe');
//search through div and add all images to an array
var images = $(container).find('img');
//console out the images array
console.log('images: ', images);
//function to shuffle our array
//using the Fisher-Yates Shuffle.
//See https://github.com/coolaj86/knuth-shuffle
function shuffleArray(array) {
var currentIndex = array.length, temporaryValue, randomIndex ;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
//shuffle our image arrray and create a new array with random ordered images
var randomImages = shuffleArray(images);
//console out the images to we can see they changed order
console.log("random image: ", randomImages);
//empty our image container and
//append our images in a new random order
//to the same container
function renderImages(array){
$(container).empty();
$.each(array, function( index, value ) {
$(container).append(value);
});
}
//call the renderImages function when our button is pressed
$(button).on("click", function(){
//render the random images to the screen
randomImages = shuffleArray(images);
renderImages(randomImages);
});
I hope this helps.
http://codepen.io/anon/pen/zkoCl

Using javascript to change width of multiple images with same id

I have a page with multiple images with the same id, I want to use javascript to size each of these depending on their original size. It only seems to check the first instance of the image and not the others, is there any way to get this working on all images?
<img id="myImg" src="compman.gif" width="100" height="98">
<img id="myImg" src="compman.gif" width="49" height="98">
<p id="demo"></p>
<button onclick="myFunction()">Try it</button>
<script>
<script>
var x = document.getElementById("myImg").width;
var yourImg = document.getElementById('myImg');
if(x < 50) {
yourImg.style.height = '100px';
yourImg.style.width = '200px';
}
</script>
The reason this isnt working is that getElementById is intended to find and return a single element with that Unique element Id. If you have two elements with the same Id, only the first is returned.
So to start off with you would need to make sure that your images share a common class, instead of the same Id, like so:
<img class="myImg" src="compman.gif" width="100" height="98">
<img class="myImg" src="compman.gif" width="49" height="98">
Then instead of using document.getElementById you should use document.querySelectorAll() which will return all elements which match the selector (as a NodeList). document.querySelectorAll on MDN
Then you can turn the NodeList returned by querySelectorAll into a normal array of images using Array#slice Array#slice on MDN.
Once done then you can itterate over each of the images (Array#forEach) and set their width/height if appropriate
So here is a possible solution for what you need to do, with comments:
var images = document.querySelectorAll('.myImg'), // Fetch all images wih the 'myImg' class
imageArray = Array.prototype.slice.call(images); // Use Array.prototype.slice.call to convert the NodeList to an array
imageArray.forEach(function (img) { // Now itterate over each image in the array
if (img.width < 50) { // If the width is less than 50
img.style.setAttribute('height', '100px'); // Set the height and width
img.style.setAttribute('width', '200px');
}
});
You will also need to make sure that the code will be executed, if you are using jQuery, put the code above in an document ready function, or if you are going to use the button which you currently have. Then put the javascript above into the myFunction function your buttons onclick event would call.
Change your id to class since id is unique for each element.
Then to change everything in the class do something like
function change(x) {
elements = document.getElementsByClassName(x);
for (var i = 0; i < elements.length; i++) {
elements[i].style.width ="100px";
}
}

jquery append 'x' number images elements applying 'x' to src and class

I have a directory with 590 pictures and my issue is being able to pull images using jquery alone from that directory and appending them which i have found out can not be done alone using jquery/javascript. alternatively i have renamed the pictures 1.jpg,2.jpg ... 590.jpg . how using jquery can i append 590 images to a div leaving me with the number of the appended element applied to the src being 'lq'+numberofappended+'.jpg' and class being 'image-'+numberofappended
as a result leaving me with the below
<div class="imagecontainer">
<img src="lq/1.jpg" class="image-1"/>
<img src="lq/2.jpg" class="image-2"/>
<img src="lq/3.jpg" class="image-3"/>
...
<img src="lq/590.jpg" class="image-590"/>
</div>
if what I have will be too extensive can i append 50 images at a time and apply a jquery pagination loading another 50 each time i reach the end of the page.
I personally know how to use append in jquery but I don't know how to individually append an image and depending on which append number it is applying it to the src and class.
Make an array of the image html.
var imgs=[];
for( i=1; i<= 590; i++){
imgs.push('<img src="lq/'+i+'/.jpg" class="image-'+i+'"/>')
}
Now you can add them all with:
$('.imagecontainer').html(imgs.join(''));
Or you could stagger loading them based on whatever works best in your UI( scroll event for example). Use slice() to get parts of the array to use for append()
Add first 50:
var first50= imgs.slice(0,50);
$('.imagecontainer').html(first50.join(''));
Here you go; store the images in an array, join them and append all at once.
var images = [];
for (var i = 1; i <= 50; i++) {
images.push('<img src="lq/'+i+'.jpg" class="image-'+i+'"/>');
}
$('.imagecontainer').append(images.join('\n'));
A for loop should do the trick,
var images = "";
for (var i = 1; i <= 5; i++) {
images += '<img src="lq/'+i+'.jpg" class="image-'+i+'"/>'
}
$('.imagecontainer').append(images);
Output
<div class="imagecontainer">
<img src="lq/1.jpg" class="image-1">
<img src="lq/2.jpg" class="image-2">
<img src="lq/3.jpg" class="image-3">
<img src="lq/4.jpg" class="image-4">
<img src="lq/5.jpg" class="image-5">
</div>
DEMO

Categories