Javascript – PNG not showing when adding dynamically - javascript

I’m a beginner JS coder and I’m struggling with the following – can anyone please help?
I’m trying to add a series of PNGs to a page using a function which will allow the placement of multiple copies of the same image and also assign a unique reference to each copy of the image.
The images are not showing in the page, plus the console.log() shows that the 2 images created by the code below both have the same position on the page.
var imgSrc = 'arrow_red.png';
function generateArrow(numArrows) {
var img = document.createElement('img');
img.src = imgSrc;
for (i = 1; i <= numArrows; i++) {
window['arrow'+i] = img;
}
}
generateArrow(2);
arrow1.style.position = 'absolute';
arrow1.style.top = '50px';
arrow1.style.left = '50px';
arrow2.style.position = 'absolute';
arrow2.style.top = '100px';
arrow2.style.left = '100px';
console.log(arrow1);
console.log(arrow2);
Why are the images not showing in the page and why does the console.log() show that the 2 images created are both using the same positional co-ordinates?

When you create a new element, it only exists in memory - - it hasn't been added to the document that the browser is currently rendering. So, it's not enough to create new elements and configure them. You must then inject them into the DOM with parentElement.appendChild(newChild).
Here's an example:
let newChild = document.createElement("img");
newChild.src = "https://static.scientificamerican.com/sciam/cache/file/D14B1C22-04F8-4FB4-95937D13A0B76545.jpg?w=590&h=393";
let parent = document.querySelector(".parent");
parent.appendChild(newChild); // <-- Now, inject the new element
img { width: 400px; }
<div class="parent"></div>
Now, in your particular case, you've got more issues than just this to work on. You are only creating a new image element one time because your line that does that is not inside of your loop. Also, the way you are referring to arrow1 and arrow2 in your code and with window['arrow' + i] indicates that you have img elements with ids already set up in your HTML, which is not an ideal approach. Next, it's much simpler to set up the CSS you'll want to work with as pre-made classes ahead of time, rather than setting up the CSS as inline styles in the script.
As my answer above indicates, you need to have a parent element that will contain the new element(s) that you create, so your solution would really look something like this:
var imgSrc = 'https://icon2.kisspng.com/20180320/rle/kisspng-arrow-computer-icons-clip-art-red-arrow-line-png-5ab19d059bfa98.5843437015215895096389.jpg';
// You can pick any pre-existing element to be the "parent"
var parent = document.getElementById("parent");
function generateArrow(numArrows) {
for (i = 1; i <= numArrows; i++) {
// The creation of the elementt and it's configuration
// need to be inside of the loop to make several of them
var img = document.createElement('img');
img.classList.add("position" + i); // Add pre-made CSS classes
img.src = imgSrc;
parent.appendChild(img); // Inject the new element inside of the parent
}
}
generateArrow(5);
/*
Instead of setting inline styles, use pre-made CSS classes
that you can just connect or disconnect to/from
*/
/* All the injected images get this: */
#parent > img { width:40px; position:absolute; }
/* These get assigned individually */
.position1 { top:50px; left:50px; }
.position2 { top:100px; left:100px; }
.position3 { top:150px; left:150px; }
.position4 { top:200px; left:200px; }
.position5 { top:250px; left:250px; }
<div id="parent"></div>

You usually add elements to DOM using document.appendChild(element);, or in your case: document.appendChild(img);. (Or any preferred parent instead of document)
Edit: removed second part addressing variable declaration, since I didn't notice the window["arrow" + i] = img.

You need to add the generated element to the DOM using the appendChild() method.
Furhermore you're actually just generating a single instance of the image because it's happening once outside of the for-loop. This is why the console shows identical screen positions for 'both' images because actually you're referring to the same image instance.
Try this:
function generateArrow(numArrows) {
var img;
for (i = 1; i <= numArrows; i++) {
img = document.createElement('img');
img.src = imgSrc;
document.body.appendChild(img);
window['arrow' + i] = img;
}
}

Related

How to reoder video tiles in Jitsi?

Last year, I wrote a bookmarklet that allowed to reorder Jitsi video tiles in alphabetic order.
Unfortunately, the script does not seem to work with the recent Jitsi versions anymore.
I have already adjusted the access to the required elements, this is working fine again.
However, the order: n attribute of the elements is ignored know, even when I set the parent to display:flex, remove the position: absolute and the left|top:n px.
I played around with the CSS and looked into documentation, but given I am no frontender, I am currently stuck.
How can I change the CSS, so that the tiles are reordered?
As a clarification, I am only looking for where I need which changes in the CSS, no scripted solution. I can take care of the scripting. Achieving a swap of two video tiles while not breaking the look would be sufficient probably.
The below information are not necessary, but might be helpful to answer the question.
Below is a screenshot showing the position in the DOM tree:
DOM tree leading to the video tiles (seems I need more reputation to embed the image)
And here is the the javascript that allows to directly access the elements:
var numberOfVideos;
function getNumberOfParticipants(){
// works
}
function getNameOfParticipant(i){
var container = $('#remoteVideos')[0];
var jChildren = $(container).children();
var jChildren2 = jChildren[1].firstChild.children;
return [jChildren2[i].getElementsByClassName("displayname")[0].innerHTML, jChildren2[i] ];
}
function sortParticipants(){
numberOfVideos = getNumberOfParticipants();
var names = new Array();
//only applicable in tiles mode!
for(i=0; i<numberOfVideos; i++) {
names[i] = new Array (2);
names[i] = getNameOfParticipant(i);
}
//sort Array
names.sort((a, b) => a[0].localeCompare(b[0]));
//reorder the tiles
for(i = 0; i < numberOfVideos; i++){
$(names[i][1]).css('order', i); //this is the line that worked in 2021, but the `order` attribute is now being ignored
}
}
https://github.com/kaiyazeera/jitsi-bookmarklets/blob/master/alphabeticSort-auto0.js
The problem could be solved by modfying the global CSS:
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = ".videocontainer { position:relative !important; top: unset !important; left: unset !important; text-align:center;overflow:hidden; }"
var css2 = document.createElement("style");
css2.type = "text/css";
css2.innerHTML = ".tile-view .remote-videos > div {flex-wrap:wrap;}"
document.body.appendChild(css)
document.body.appendChild(css2)

JQuery append image not showing

For this code block
$(document).ready(() => {
for (let i = 0; i < 10; i++) {
$("#main").append(factory());
}
});
this will show the image:
function factory() {
return $('<image class="champ-icon rounded-circle" src="resources/irelia.jpg" />');
}
while this doesn't
function factory() {
let $champIcon = $(document.createElement("image"))
.addClass("champ-icon rounded-circle")
.attr("src", "resources/irelia.jpg");
return $champIcon;
}
I'm using Bootstrap 4 as well.
The page currently is just a static mock up. I want to dynamically build elements from data given to it by a local server.
I literally just messed around with HTML/CSS and jQuery over the weekend so I'm not sure what went wrong here. Shouldn't both function return the same jQuery object?
Thanks!
CSS class
.champ-icon {
width: 100px;
height: 100px;
}
Edit: creating it with normal javascript works as well.
function factory() {
let img = new Image();
img.src = "resources/irelia.jpg";
img.className = "champ-icon rounded-circle";
return img;
That's because you are trying to programmatically create <image> element in html, which... doesn't exist. To insert element on a page you should use <img src="">, not <image...>. Change this line
let $champIcon = $(document.createElement("image"))
to
let $champIcon = $(document.createElement("img"))
And it should work.

Generate array of image in javascript inside <div>

I need to make the background image in div tag and it has to change automatically, I already put the array of images inside the javascript, but the images is not showing when i'm run the site.The background should behind the menu header.
This is the div
<div style="min-height:1000px;position:relative;" id="home">
below of the div is containing the logo, menu and nav part.
<div class="container">
<div class="fixed-header">
<!--logo-->
<div class="logo" >
<a href="index.html">
<img src="images/logo.png" alt="logo mazmida" height="142" width="242">
</a>
</div>
<!--//logo-->
This is the javascript
<script>
var imgArray = [
'images/1.jpg',
'images/2.jpg',
'images/3.jpg'],
curIndex = 0;
imgDuration = 2000;
function slideShow() {
document.getElementID('home').src = imgArray[curIndex];
curIndex++;
if (curIndex == imgArray.length) { curIndex = 0; }
setTimeout("slideShow()", imgDuration);
}
slideShow();
You have a few issues with your script. I've made a live JSbin example here:
https://jsbin.com/welifusomi/edit?html,output
<script>
var imgArray = [
'https://upload.wikimedia.org/wikipedia/en/thumb/0/02/Homer_Simpson_2006.png/220px-Homer_Simpson_2006.png',
'https://upload.wikimedia.org/wikipedia/en/thumb/0/0b/Marge_Simpson.png/220px-Marge_Simpson.png',
'https://upload.wikimedia.org/wikipedia/en/a/aa/Bart_Simpson_200px.png'
];
var curIndex = 0;
var imgDuration = 1000;
var el = document.getElementById('home');
function slideShow() {
el.style.backgroundImage = 'url(' + imgArray[curIndex % 3] + ')';
curIndex++;
setTimeout("slideShow()", imgDuration);
}
slideShow();
</script>
There are a few issues with your script:
On the element since it's a div not an img, you need to set style.backgroundImage instead of src. Look at https://developer.mozilla.org/en-US/docs/Web/CSS/background for other attributes to related to background image CSS
Also it's document.getElementById
Optimizations
And you can use mod % trick to avoid zero reset
Use setInterval instead of setTimeout
Further optimzations
Use requestAnimationFrame instead of setTimeout/setInterval
I suggest getting familiar with your browser debugging tools which would help identify many of the issues you face.
document.getElementID('home').src = imgArray[curIndex]
You are targeting a div with an ID of home, but this is not an Image element (ie ,
But since you want to alter the background colour of the DIV, then you use querySelector using javascript and store it in a variable, then you can target the background property of this div (ie Background colour).
I hope this helps.
You are trying to change the src property of a div, but divs do not have such property.
Try this:
document.getElementById('home').style.backgroundImage = "url('" + imgArray[curIndex] + "')"
This changes the style of the target div, more precisely the image to be used as background.
As you want to change the background image of the div, instead of document.getElementID('home').src = imgArray[curIndex] use
document.getElementById("#home").style.backgroundImage = "url('imageArray[curIndex]')";
in JavaScript or
$('#home').css('background-image', 'url("' + imageArray[curIndex] + '")'); in jquery.
To achieve expected result, use below option of using setInterval
Please correct below syntax errors
document.getElementID to document.getElementById
.src attribute is not available on div tags
Create img element and add src to it
Finally use setInterval instead of setTimeout outside slideShow function
var imgArray = [
'http://www.w3schools.com/w3css/img_avatar3.png',
'https://tse2.mm.bing.net/th?id=OIP.ySEgAgJIlDQsIQTu_MeoLwHaHa&pid=15.1&P=0&w=300&h=300',
'https://tse4.mm.bing.net/th?id=OIP.wBAPnR04OfXaHuFI9Ny2bgHaE8&pid=15.1&P=0&w=243&h=163'],
curIndex = 0;
imgDuration = 2000;
var home = document.getElementById('home')
var image = document.createElement('img')
function slideShow() {
if(curIndex != imgArray.length-1) {
image.src = imgArray[curIndex];
home.appendChild(image)
curIndex++;
}else{
curIndex = 0;
}
}
setInterval(slideShow,2000)
<div style="position:relative;" id="home"></div>
code sample - https://codepen.io/nagasai/pen/JLKvME

How to load several images in the same place

I have created an html document that uses javascript to connect to xml and get the name of a picture to load using this CSS :
#container {
width:800px;
}
#left {
top:10%;
position: relative;
float: left;
width:200px;
left:30px;
}
#right {
position:absolute;
top: 0px;
right: 300px;
z-index:-1;
}
And this code:
var TestP = new Array();
function loadImg(n){
TestP[n] = xmlDoc.documentElement.childNodes[n].textContent;
var img = document.createElement('img');
alert(TestP[n]);
img.src = TestP[n];
alert(n);
alert(TestP[n]);
document.getElementById('right').appendChild(img);
A part of the HTML :
<li>Part 1</li>
The thing is when I first click on the link, everything works well, but when I click another time, I will get two images, each at a different position. I want to have the second image take the exact same place, beeing on top of the first one.
elem = document.getElementById( 'right' );
child = elem.firstChild;
if ( child )
elem.replaceChild( img, child );
else
elem.appendChild( img );
Sounds like you just want one image, of which you change the URL each time.
Define in your HTML:
<img id="image">
and use in JavaScript:
var TestP = []; // cleaner way for creating an array
function loadImg(n) {
TestP[n] = xmlDoc.documentElement.childNodes[n].textContent;
document.getElementById('image').src = TestP[n];
}
Also note that HTML5 introduces some semantics, one of which being binding event handlers through JavaScript instead of through HTML.
don't create a new image, but replace the src attribute.
first give the image an id, so you can find it:
<img id="myimage" src="..."/>
changing it goes like this:
document.getElementById("myimage").src = "...new source...";
another option:
var TestP = new Array();
function loadImg(n) {
TestP[n] = xmlDoc.documentElement.childNodes[n].textContent;
var myImage = document.getElementById("myimage");
if(myImage != null) {
myImage.parentNode.removeChild(myImage);
}
var img = document.createElement('img');
img.src = TestP[n];
img.id = "myimage";
document.getElementById('right').appendChild(img);
}
well, you are doing it with .appendChild(). then you call it again and it appends second child. so, you have two options. before you append the second image, remove the old one, OR, just replace it.

Image animation keeps requesting the images

I test the code in IE7, FF, Chrome, Safari and this problem occurs in Firefox only.
I have checked that the problem only occurs in FF 3.5.x, but not FF 3.0.x.
I want to make an image animation which has 10 images in total.
Currently, I use the following code to do it:
for (var i=1;i<=10;i++){
img[i] = new Image();
img[i].src = "images/survey/share_f"+i+".jpg"
}
var cornerno = 0;
function imganimate(){
$("#surveyicon").attr("src",img[cornerno].src);
//some logic to change the cornerno
setTimeout("imganimate()",1000);
}
And then change an element's src to loop through the array "img".
however, firefox keeps requesting the images continuous (I expect it only requests each unique image just once).
What should I do?
img is undefined. just add a line "var img = new Array();" before "for (var i=1;i<=10;i++){"
var img = new Array();
for (var i=1;i<=10;i++){
img[i] = new Image();
img[i].src = "images/survey/share_f"+i+".jpg";
}
var cornerno = 0;
function imganimate(){
cornerno %= 10;
cornerno++;
$("#surveyicon").attr("src",img[cornerno].src);
setTimeout("imganimate()",1000);
}
imganimate();
Try composing the images into a single image file like a sprite map and then use CSS positioning to shift the image around as a background image. It will be much faster and avoid any reloads.
You've already created ten DOM nodes, set their src and loaded the images. Why would you set the src again? You want to rotate those ten nodes in and out now. You can either toggle style.display or remove and insert the nodes.
Here's my suggestion. I'm not well versed in JQuery so there may be a few additional shortcuts I've overlooked:
var imgAmt = 10;
img = [];
for (var i=1;i<=imgAmt;i++){
img[i] = document.createElement("img");
img[i].src = "images/survey/share_f"+i+".jpg"
img[i].style.display = "none";
$("#surveyicon").appendChild(img[i]);
}
imganimate();
var cornerno = 0;
function imganimate(){
cornerno++;
cornerno = cornerno > imgAmt ? 1 : cornerno;
for (var i=1;i<=imgAmt;i++){
// hide all images but the index that matches cornerno:
img[i].style.display = i==cornerno ? "" : "none";
}
setTimeout(imganimate,1000);
}
This seems a bug in FF3.5.x.
Not sure whether the bug has already been fixed.

Categories

Resources