function newHeader (header) {
var head = document.createElement('h'+ header);
var hText = document.createTextNode('text for h'+ header);
head.appendChild(hText);
document.body.appendChild(head);
}
function newPara (para) {
var newP = document.createElement('p');
var newPText = document.createTextNode("text for p" + para);
newP.appendChild(newPText);
var intoH = document.getElementByTagName('h' + header);
intoH.item(0).appendChild(newP);
}
for (i = 1; i <= 6; i++) {
newHeader(i);
}
for (i = 1; i <= 6; i++) {
newPara(i);
}
What am I doing wrong?
I want to dynamically create the headers and place paragraphs with the text inside them. I was attempting to use the item() to appendChild to place the new paragraph text inside the headers accordingly but it doesn't work. I get the headers to show , but not the paragraph.
Please help!
thank you!
You're using header variable when is not defined (you should replace it by para), Also you miss s in getElementByTagName should be getElementsByTagName and that will return an array of elements so you can specify the first using [0] instead of item(0) :
document.getElementsByTagName('h' + para)[0];
Hope this helps.
function newHeader (header) {
var head = document.createElement('h'+ header);
var hText = document.createTextNode('text for h'+ header);
head.appendChild(hText);
document.body.appendChild(head);
}
function newPara (para) {
var newP = document.createElement('p');
var newPText = document.createTextNode("text for p" + para);
newP.appendChild(newPText);
var intoH = document.getElementsByTagName('h' + para)[0];
intoH.appendChild(newP);
}
for (i = 1; i <= 6; i++) {
newHeader(i);
}
for (i = 1; i <= 6; i++) {
newPara(i);
}
Related
I have been playing with this code for a while and I was wondering why when I try to add img’s to the array on the js code makes the images appear on DOM but also makes a bunch of Undefined elements appear, How can I just make the 15 images appear without the undefined? Thanks
enter link description here
var previous = document.getElementById('btnPrevious')
var next = document.getElementById('btnNext')
var gallery = document.getElementById('image-gallery')
var pageIndicator = document.getElementById('page')
var galleryDots = document.getElementById('gallery-dots');
var images = ["https://exoplanets.nasa.gov/internal_resources/1763/",
"https://cdn.britannica.com/56/234056-050-0AC049D7/first-image-from-James-Webb-Space-Telescope-deepest-and-sharpest-infrared-image-of-distant-universe-to-date-SMACS-0723.jpg",
"https://assets.newatlas.com/dims4/default/ac389ce/2147483647/strip/true/crop/1620x1080+150+0/resize/1200x800!/quality/90/?url=http%3A%2F%2Fnewatlas-brightspot.s3.amazonaws.com%2Farchive%2Funiverse-expanding-acceleration-1.jpg",
"https://media.newyorker.com/photos/590966ee1c7a8e33fb38d6cc/master/w_2560%2Cc_limit/Nissan-Universe-Shouts.jpg",
"https://www.thoughtco.com/thmb/NY5k_3slMRttvtS7mA0SXm2WW9Q=/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/smallerAndromeda-56a8ccf15f9b58b7d0f544fa.jpg",
"https://static.scientificamerican.com/sciam/cache/file/05B8482C-0C04-4E41-859DCCED721883D2_source.jpg?w=590&h=800&7ADE2895-F6E3-4DF4-A11F51B652E9FA88",
"https://qph.cf2.quoracdn.net/main-thumb-66277237-200-huqebnzwetdsnnwvysbxemlskpcxnygf.jpeg",
"http://www.pioneertv.com/media/1090/hero_shot_1080x720.jpg?anchor=center&mode=crop&width=600&height=400&rnd=133159257140000000",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRSWFW1EpMNFM5-dbZEUUnzJkzT3KbUCeuhPHx_eseFCpPeX4Q_DIVPopjS0LeKVmKdQho&usqp=CAU",
"https://cdn.mos.cms.futurecdn.net/rwow8CCG3C3GrqHGiK8qcJ.jpg",
"https://static.wixstatic.com/media/917d103965314e2eacefed92edb6492c.jpg/v1/fill/w_640,h_356,al_c,q_80,usm_0.66_1.00_0.01,enc_auto/917d103965314e2eacefed92edb6492c.jpg",
"https://astronomy.com/~/media/A5B9B6CF36484AB9A6FFAE136C55B355.jpg",
"https://discovery.sndimg.com/content/dam/images/discovery/fullset/2022/9/alien%20planet%20GettyImages-913058614.jpg.rend.hgtvcom.616.411.suffix/1664497398007.jpeg",
"https://images.newscientist.com/wp-content/uploads/2017/06/21180000/planet-10-orange-blue-final-small.jpg?crop=16:9,smart&width=1200&height=675&upscale=true",
"https://images.hindustantimes.com/img/2022/07/20/1600x900/Viral_Instagram_Planet_Rainbow_Nasa_1658316556293_1658316573815_1658316573815.PNG"
]
for (var i = 0; i < 15; i++) {
images.push({
title: "Image " + (i + 1),
source: images[i]
});
}
var perPage = 8;
var page = 1;
var pages = Math.ceil(images.length / perPage)
// Gallery dots
for (var i = 0; i < pages; i++){
var dot = document.createElement('button')
var dotSpan = document.createElement('span')
var dotNumber = document.createTextNode(i + 1)
dot.classList.add('gallery-dot');
dot.setAttribute('data-index', i);
dotSpan.classList.add('sr-only');
dotSpan.appendChild(dotNumber);
dot.appendChild(dotSpan)
dot.addEventListener('click', function(e) {
var self = e.target
goToPage(self.getAttribute('data-index'))
})
galleryDots.appendChild(dot)
}
// Previous Button
previous.addEventListener('click', function() {
if (page === 1) {
page = 1;
} else {
page--;
showImages();
}
})
// Next Button
next.addEventListener('click', function() {
if (page < pages) {
page++;
showImages();
}
})
// Jump to page
function goToPage(index) {
index = parseInt(index);
page = index + 1;
showImages();
}
// Load images
function showImages() {
while(gallery.firstChild) gallery.removeChild(gallery.firstChild)
var offset = (page - 1) * perPage;
var dots = document.querySelectorAll('.gallery-dot');
for (var i = 0; i < dots.length; i++){
dots[i].classList.remove('active');
}
dots[page - 1].classList.add('active');
for (var i = offset; i < offset + perPage; i++) {
if ( images[i] ) {
var template = document.createElement('div');
var title = document.createElement('p');
var titleText = document.createTextNode(images[i].title);
var img = document.createElement('img');
template.classList.add('template')
img.setAttribute("src", images[i].source);
img.setAttribute('alt', images[i].title);
title.appendChild(titleText);
template.appendChild(img);
template.appendChild(title);
gallery.appendChild(template);
}
}
// Animate images
var galleryItems = document.querySelectorAll('.template')
for (var i = 0; i < galleryItems.length; i++) {
var onAnimateItemIn = animateItemIn(i);
setTimeout(onAnimateItemIn, i * 100);
}
function animateItemIn(i) {
var item = galleryItems[i];
return function() {
item.classList.add('animate');
}
}
// Update page indicator
pageIndicator.textContent = "Page " + page + " of " + pages;
}
showImages();
I checked your code and make it work with a small modification.
You are reusing the same array with the links of images and push inside the new object with the shape of { title, source }.
You just need to do this changes:
Change the name of your array of images. Something from images to arrayOfImages.
const arrayOfImages = ["https://exoplanets.nasa.gov/internal_resources/1763/", ...]
Declare an empty array before your first for loop. Make something like const images = []
On your for loop, instead of loop over the images variable, do it over the arrayOfImages variable.
const images = [];
for (var i = 0; i < 15; i++) {
images.push({
title: "Image " + (i + 1),
source: arrayOfImages[i]
});
}
With those changes, everything works for me.
Also, as a recommendation, try to avoid the var keyword. If you want more details about this, this answer is very helpful: https://stackoverflow.com/a/50335579/17101307
You can use Array#map to create a new array of objects from the array of URLS, then replace the original array.
images = images.map((x, i) => ({
title: "Image " + (i + 1),
source: x
}));
I have a function that crawls infos from tmdb. i want to work with that response. i do for example search for a movie and want to put the results(titles and the poster-images) into a table with a button.
That works fine.
For that i have a loop that creates a table with entries every loop. In 1 entry i have a button, that is supposed to call another function and give it the value(form the poster-path the movie has) that is set in the specific loop. Works partially...Problem is: the value given to the new fuction is always the last value (value of the last loop). I dont know how to fix that :/
I already tried an "Immediately-Invoked Function Expression"(found in this forum) which looks like this
for (var i = 0; i < 3; i++) {
(function(index) {
console.log('iterator: ' + index);
})(i);
}
Same Problems still :/
thats my script ("bbcode" and "imglink" were set before this)
if (this.status === 200) {
var jsonResponse = JSON.parse(this.responseText);
totalresults = jsonResponse.total_results;
if (totalresults === 0){ noresult(); }
if (totalresults === 1){ oneresult(); }
else {
var x = document.createElement("TABLE");
x.setAttribute("id", "myTable");
x.setAttribute("border", "1");
document.getElementById("log").appendChild(x);
for (var j = 0; j < totaresults; j++) {
(function(i) {
posterpath = jsonResponse.results[i].poster_path;
newbbcode = bbcode.replace(imglink, "http://image.tmdb.org/t/p/w400"+ posterpath);
var y = document.createElement("TR");
y.setAttribute("id", "myTr" + i);
document.getElementById("myTable").appendChild(y);
var z = document.createElement("TD");
var t = document.createTextNode(jsonResponse.results[i].title);
z.appendChild(t);
document.getElementById("myTr" + i).appendChild(z);
var z = document.createElement("TD");
var t = document.createElement("IMG");
t.setAttribute("src", "http://image.tmdb.org/t/p/w92"+jsonResponse.results[i].poster_path);
z.appendChild(t);
document.getElementById("myTr" + i).appendChild(z);
var z = document.createElement("TD");
var t = document.createElement("INPUT");
t.setAttribute("type","button");
t.setAttribute("value","pick this");
t.addEventListener("click", function(){workwithnewbbcode(newbbcode)} );
z.appendChild(t);
document.getElementById("myTr" + i).appendChild(z);
})(j);
}
}
Maybe someone has a very simple (noob friendly^^) idea to do that with javascript.
Thank you guys!
EDIT: Thanks to Jaromanda X for the solution!
instead of
newbbcode = bbcode.replace(imglink, "http://image.tmdb.org/t/p/w400"+ posterpath);
just add var
var newbbcode = bbcode.replace(imglink, "http://image.tmdb.org/t/p/w400"+ posterpath);
OR
if (this.status === 200) {
var jsonResponse = JSON.parse(this.responseText);
totalresults = jsonResponse.total_results;
if (totalresults === 0) {
noresult();
} else if (totalresults === 1) {
oneresult();
} else {
var table = document.createElement("TABLE");
table.id = "myTable";
table.border = "1";
jsonResponse.results.forEach(function(result) {
var posterpath = result.poster_path;
var newbbcode = bbcode.replace(imglink, "http://image.tmdb.org/t/p/w400" + posterpath);
var tr = document.createElement("TR");
var td1 = document.createElement("TD");
td1.appendChild(document.createTextNode(result.title));
tr.appendChild(td1);
var td2 = document.createElement("TD");
var img = document.createElement("IMG");
img.src = "http://image.tmdb.org/t/p/w92" + posterpath;
td2.appendChild(img);
tr.appendChild(td2);
var td3 = document.createElement("TD");
var input = document.createElement("INPUT");
input.type = "button";
input.value ="pick this";
input.addEventListener("click", function() {
workwithnewbbcode(newbbcode);
});
td3.appendChild(input);
tr.appendChild(td3);
table.appendChild(tr);
});
document.getElementById("log").appendChild(table);
}
}
Consider the following example:
for (var i=0;i<10;i++){
setTimeout(function(){
console.log(i);
},1000);
}
You will always get 10 in the output because by the time the nested function is called, the variable i already reached the end of the loop.
In your case, your response object arrives in an XHR callback. This has the same flow as setTimeout. You can create a function wrapper to keep the iterator variable in the call stack:
var myfunc=function(x){ //a function that returns a function
setTimeout(function(){
console.log(x);
},1000);
}
for (var i=0;i<10;i++) myfunc(i);
I'm really new to javascript from C# and i'm having a little trouble. I wrote this function to make adding menu's a bit easier on my site. It works well except I can't seem to give my div's an individual url, even though I can give them an individual innerHtml.
I've been stuck trying different things such as divs[i].location.url etc.. but I can't seem to have anything work. My current solution has each div link to /contact.html which I'm a little confused by.
function DrawMainMenu() {
var btns = [
["About", "/about.html"],
["Portfolio", "/portfolio.html"],
["Resume", "/resume.html"],
["Contact", "/contact.html"]
];
var numOfBtns = btns.length;
var divs = new Array(numOfBtns);
for (var i = 0; i < numOfBtns; i++) {
divs[i] = document.createElement("div");
divs[i].className = "menuBtn";
divs[i].innerHTML = btns[i][0];
divs[i].style.height = (30 / numOfBtns) + "%";
divs[i].style.lineHeight = 3.5;
var link = btns[i][1];
divs[i].addEventListener('click', function() {
location.href = link;
}, false);
document.getElementById("buttons").appendChild(divs[i]);
}
}
Thanks
The problem is that the variable link gets overwritten each iteration, so when the event handler it gets link, which is the string '/contact.html', since that was the last value given to it.
You can try setting onclick attribute to elements, which will store the variable in the attribute onclick. Therefore, it will have the old and correct value.
function DrawMainMenu() {
var btns = [
["About", "/about.html"],
["Portfolio", "/portfolio.html"],
["Resume", "/resume.html"],
["Contact", "/contact.html"]
];
var numOfBtns = btns.length;
var divs = new Array(numOfBtns);
for (var i = 0; i < numOfBtns; i++) {
divs[i] = document.createElement("div");
divs[i].className = "menuBtn";
divs[i].innerHTML = btns[i][0];
divs[i].style.height = (30 / numOfBtns) + "%";
divs[i].style.lineHeight = 3.5;
var link = btns[i][1];
divs[i].setAttribute('onclick', 'location.href = "' + link + '"');
document.getElementById("buttons").appendChild(divs[i]);
}
}
DrawMainMenu();
<div id="buttons"><div>
Updated answer
Here we make use of closures. Using a closure (closing the values of link) we bind the value to the scope of the click handler.
function DrawMainMenu() {
var btns = [
["About", "/about.html"],
["Portfolio", "/portfolio.html"],
["Resume", "/resume.html"],
["Contact", "/contact.html"]
];
var numOfBtns = btns.length;
var divs = new Array(numOfBtns);
for (var i = 0; i < numOfBtns; i++) {
(function() {
divs[i] = document.createElement("div");
divs[i].className = "menuBtn";
divs[i].innerHTML = btns[i][0];
divs[i].style.height = (30 / numOfBtns) + "%";
divs[i].style.lineHeight = 3.5;
var link = btns[i][1];
document.getElementById("buttons").appendChild(divs[i]);
divs[i].addEventListener('click', function() {
location.href = link;
}, false);
}());
}
}
DrawMainMenu();
<div id="buttons"><div>
Apologies here is another question regarding my javascript image replacement script.
So far with the help of stackexchangers i have this like so and it's working great. But now I need to make another little change:
var paths = ["add","clear","copy","delete"];
var fullPaths = paths.map(function(x) { return "img[src*='" + x + "']"; } );
var imgs = document.querySelectorAll(fullPaths);
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i],
iClass = img.className,
iSrc = ###THE CORRESPONDING NAME IN THE ARRAY###,
span = $('<span />', {'class': 'iconfont '+iClass+' '+iSrc,
title : img.parentNode.title
});
$(img).replaceWith(span);
}
I want iSrc to be the name of the image in the array. So that when the image with <src="edit.png" class="iconmini> is replaced, the span has the classes: .iconfont, .iconmini, and, .edit
I have tried doing the following:
iSrc = paths[i]
but that doesn't work obviously and adds the wrong classes :)
I have another question, too, regarding my script but I will ask that as a seperate question. Thanks!
EDIT:
Thanks again for everyone who has helped me here. I have now added an extra bit to my code that will also set the image title, and thought that I would post it here, it might help someone in the future.
Some of the images have titles and some dont like when they wrapped in an anchor. So I have done the following which seems to work for me:
var paths = ["add","clear","copy","delete"];
var fullPaths;
var imgs;
for(var p=0; p<paths.length; p++) {
fullPaths = "img[src*='" + paths[p] + "']";
imgs = document.querySelectorAll(fullPaths);
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
if ($(img).attr('title')) {
iTitle = img.title;
} else {
iTitle = img.parentNode.title;
}
iClass = img.className;
iSrc = paths[p];
span = $('<span />', {'class': 'iconfont '+iClass+' '+iSrc,
title : iTitle
});
$(img).replaceWith(span);
}
}
This is the same approach that #bfavaretto suggested but with the use of jQuery loops and simplified a bit:
var paths = ["add", "clear", "copy", "delete"];
$.each(paths, function (i, path) {
$("img[src*='" + path + "']").each(function () {
var $span = $('<span />', {
class: 'iconfont ' + this.className + ' ' + path,
title: this.parentNode.title
});
$(this).replaceWith($span);
});
});
You could get the images separately for each path/class, so they won't be mixed:
var paths = ["add","clear","copy","delete"];
var fullPaths;
var imgs;
for(var p=0; p<paths.length; p++) {
fullPaths = "img[src*='" + paths[p] + "']";
imgs = document.querySelectorAll(fullPaths);
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i],
iClass = img.className,
iSrc = paths[p],
span = $('<span />', {'class': 'iconfont '+iClass+' '+iSrc,
title : img.parentNode.title
});
$(img).replaceWith(span);
}
}
I like bfavaretto's answer, but if you don't want to get the images separately, you could always add this lame-ish workaround:
var paths = ["add","clear","copy","delete"];
var fullPaths = paths.map(function(x) { return "img[src*='" + x + "']"; } );
var imgs = document.querySelectorAll(fullPaths);
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i],
iClass = img.className;
//workaround start
var iSrc;
for(var j = 0; j < paths.length; j++) {
if(img.src.split('/').pop().indexOf(paths[i]) != -1) {
iSrc = paths[i];
break;
}
}
//workaround end
span = $('<span />', {'class': 'iconfont '+iClass+' '+iSrc,
title : img.parentNode.title
});
$(img).replaceWith(span);
}
I am new to javascript. I have a table of content which I want to rearrange its row and column based on user's window size using window.onresize.
window.onresize = function () {
var w = window.innerWidth;
var nocolumn = Math.floor(w / 252);
if (nocolumn == 0) {
nocolumn = 1;
}
var table = document.getElementById("MainContent_DataList1");
var tbody = table.getElementsByTagName("tbody")[0];
var link = tbody.getElementsByTagName("a");
var norow = Math.ceil(link.length / nocolumn);
tbody.innerHTML = "";
console.log(norow + " " + link.length + " " + nocolumn);
for (var i = 0; i < norow; i++) {
var row = document.createElement("tr");
tbody.appendChild(row);
for (var j = 0; j < nocolumn; j++) {
var cell = document.createElement("td");
row.appendChild(cell);
if ((i * nocolumn + j) < link.length) {
cell.appendChild(link[i * nocolumn + j]);
}
}
}
};
I dont understand why the variable "link" array becomes empty after I use innerHTML = ""; but I stored it before its cleared. Is it somewhere I did wrongly or there are other ways to do this?
When you delete the innerHTML you delete the DOM objects thus every reference to them will point to null.
A work around it will be to clone these objects:
function clone(obj) {
if (null == obj || "object" != typeof obj) return obj;
var copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
}
return copy;
}
window.onresize = function () {
var w = window.innerWidth;
var nocolumn = Math.floor(w / 252);
if (nocolumn == 0) {
nocolumn = 1;
}
var table = document.getElementById("MainContent_DataList1");
var tbody = table.getElementsByTagName("tbody")[0];
var tmp = tbody.getElementsByTagName("a");
var link = clone(tmp);
var norow = Math.ceil(link.length / nocolumn);
tbody.innerHTML = "";
...
}
Credit for the clone() method: https://stackoverflow.com/a/728694/1057429
As other answers have suggested, getElementsByTagName returns a live NodeList. Therefore, when you delete all the elements from the body, the NodeList is updated to contain no nodes.
As an alternative, you can use querySelectorAll, which returns a static NodeList, or use getElementsByTagName and assign references to an array before clearing the nodes from the body, e.g.
function getNodes() {
var tbody = document.body || document.getElementsByTagName('body')[0];
var nodes, link;
if (tbody.querySelectorAll) {
link = tbody.querySelectorAll('*');
} else {
nodes = tbody.getElementsByTagName("*");
link = [];
for (var i=0, iLen=nodes.length; i<iLen; i++) {
link[i] = nodes[i];
}
}
return link;
}