Error using insertBefore & appendChild while creating element - javascript

Trying to append a button to both the top and bottom of the body tag, however it's only performing whichever one of the two is last. Am I missing something obvious here?
var msg_node = document.createElement("a");
msg_node.setAttribute("onclick", "collapseAll()");
msg_node.setAttribute("href", "javascript:void(0)");
msg_node.setAttribute("class", "kc_button");
var msg_textnode = document.createTextNode('COLLAPSE ALL');
msg_node.appendChild(msg_textnode);
document.getElementsByTagName('body')[0].appendChild(msg_node); // supposed to make button
document.body.insertBefore(msg_node, document.body.children[0]); // makes only this button

Clone the node before appending it the second time:
var msg_node = document.createElement("a");
msg_node.setAttribute("onclick", "collapseAll()");
msg_node.setAttribute("href", "javascript:void(0)");
msg_node.setAttribute("class", "kc_button");
var msg_textnode = document.createTextNode('COLLAPSE ALL');
msg_node.appendChild(msg_textnode);
document.getElementsByTagName('body')[0].appendChild(msg_node); // supposed to make button
document.body.insertBefore(msg_node.cloneNode(true), document.body.children[0]); // makes only this button

Related

Add element to a div with javascript

I want to add an element (child, div) to a mother-div, that already has one or more children. I made a script for this action but when I execute the script I am not able to manipulate style attributes afterwards. So I assume I did something wrong in my creation-script. I also added a console message (end of the script) and that also indicates there are no style attributes filled in at the new div. So, please could someone indicate what the reason is...
As I am quite new to javascript I assume the reason is quite simple. But although I checked many other questions and solutions, I do not get the proper solution for my issue. I think it should be in appendChild or insertBefore.
function preparevideo(videonaam, titel) {
// add a div to the video-div
const nieuwetitel = document.createElement("div");
// give the new div an id so it will be unique
nieuwetitel.id = videonaam + '-id';
// give the div a class for the markup
nieuwetitel.className = 'page-roel-video-titel';
// create the text in the div
const textnode = document.createTextNode(titel);
// add the textnode to the div
nieuwetitel.appendChild(textnode);
// find the element where the new div should be added to
let videomodule = document.getElementById(videonaam);
// and finally add the new div to the video-div, as the first child
videomodule.insertBefore(nieuwetitel, videomodule.children[0]);
console.log('-------after adding div------');
console.log('-------complete style of titleblock------');
console.log(document.getElementById(videonaam + '-id').style);
console.log('prepare video afgerond');
}
preparevideo("naam1","Eerste video");
<div id="naam1"></div>
As you didn't set any style attribute before console.log that's why you didn't get any result. After implementing some style, you can log the the style. Then you will see the difference.
Here I added some style before the console.log
function preparevideo(videonaam, titel) {
// add a div to the video-div
const nieuwetitel = document.createElement("div");
// give the new div an id so it will be unique
nieuwetitel.id = videonaam + '-id';
// give the div a class for the markup
nieuwetitel.className = 'page-roel-video-titel';
// create the text in the div
const textnode = document.createTextNode(titel);
// add the textnode to the div
nieuwetitel.appendChild(textnode);
// find the element where the new div should be added to
let videomodule = document.getElementById(videonaam);
// and finally add the new div to the video-div, as the first child
videomodule.insertBefore(nieuwetitel, videomodule.children[0]);
// Applying style
document.getElementById(videonaam + '-id').style.backgroundColor = 'red';
document.getElementById(videonaam + '-id').style.color = 'white'
console.log('-------after adding div------');
console.log('-------complete style of titleblock------');
console.log(document.getElementById(videonaam + '-id').style);
console.log('prepare video afgerond');
}
preparevideo("naam1","Eerste video");
<div id="naam1"></div>
You already gave it a class, you can target it in your css and added the needed styles
The problem is that there is no unique id value for nieuwetitel element generated. When you use getElementById() method you get only first element from DOM.

onclick inside forEach, value parameter only refers to last element

I have a list of anchor in my html, I want to make their href editable.
Everything fine, but the validation step (last onclick) refers to the last anchor instead of the current one
var anchors = document.querySelectorAll('.home-content a');
var col = document.querySelectorAll('.home-content > article');
anchors.forEach((k)=> {
let linkpanel = document.getElementById('link-edit-panel'); //This element is a single div in my html
let linkpanelvalidate = document.getElementById('validate-link'); //the button inside the said div
let editinput = linkpanel.querySelector('input'); //the input inside this div
//For each anchors, I add a button that will let user show the "linkpanel" div to edit the href of this anchor
let editbut = document.createElement('div');
let linktxt = k.href;
editbut.classList.add('edit-but','toremove');
editbut.innerHTML = "<i class='fas fa-link'></i>";
//I put this new element to the current anchor
k.appendChild(editbut);
console.log(k); // this to show me the full list of anchors
/* PROBLEM START HERE */
//click on the "edit" button
editbut.onclick = ()=>{
console.log(k); //Here, it shows the good anchor!
}
//click on the "validate" button
linkpanelvalidate.onclick = ()=>{
console.log(k); //Here, it shows the very last anchor...
}
});
I tried to put the element inside a constant
const ttt = k;
It does not change a thing.
Thank you for your help
We are facing here a classical forEach bubbling misunderstand (and I was blind not to see it)
When the click on the validate button occures, the call is made from the "main" bubble (outside the loop function if you need to picture it) so naturaly, it returns the last occurrence of the loop when we print the value in the console for example.
Solution
There is many solutions, you can store these values in an array to use each of them later
var arr = [];
node.forEach((v)=>{
arr.push(v);
});
Or, you don't want to deal with an array and want to keep it simple, like me, and you create your button during the forEach loop event, like this
node.forEach((v)=>{
let btn = document.createElement('button');
document.body.appendChild(btn);
btn.onclick = ()=> {
console.log(v); //it is the current value, not the last one
//you can create another button here and put his onclick here, the value will still remains etc
}
});

appendChild odd behavior in javascript

In the procedure of creating and appending elements to a webpage, I faced an odd behavior of javascript, that is replacing a child with another instead of appending. here is the code:
var window = document.createElement("div"); //the minesweeper game window
window.setAttribute("class", "window");
document.body.appendChild(window);
var title_bar = document.createElement("div");//the title bar of the window
title_bar.setAttribute("class", "title-bar");
window.appendChild(title_bar);
var game_title = document.createElement("span");//the title of the game
game_title.setAttribute("id", "game-title");
game_title.innerHTML = "Minesweeper Online - Beginner!";
title_bar.appendChild(game_title);
var right_corner_div = document.createElement("div");// right corner buttons
title_bar.appendChild(right_corner_div);
var btn_minimize = document.createElement("span");//the minimize button
btn_minimize.setAttribute("class", "btn");
btn_minimize.setAttribute("id", "btn-minimize");
btn_minimize.innerHTML = "-";
right_corner_div.appendChild(btn_minimize);
var btn_close = document.createElement("span");//the close button
btn_close.setAttribute("class", "btn");
btn_close.setAttribute("id", "btn-close");
btn_close.style.marginLeft = "3px";
btn_close.innerHTML = "×";
right_corner_div.appendChild(btn_close);
var top = document.createElement("div");//top of window div, underneath the title bar
title_bar.setAttribute("class", "top");
window.appendChild(top);
but unlike what I expect to see as the result, the latest div with the class attribute of top replaces the first div with the class attribute of title-bar. why does this happen?
You have title_bar here instead of top (second last line in your question):
var top = document.createElement("div");
*title_bar*.setAttribute("class", "top");
window.appendChild(top);
Replace that with top and it should work.
By the way, don't name a variable window in a browser, since that is what the global object reference is assigned to. Call your variable game_window or something else along those lines instead.
Also you probably don't care about the actual HTML class attribute of your elements and should set the className property directly instead:
top.className = "top"; // instead of top.setAttribute("class", "top");

Formatting a href link with appendChild, setAttribute, etc

I am attempting to populate a list with href links via javascript.
Here is an example of the html I would like to create:
<li> Complete blood count</li>
Where "#modal-one" displays a pop up.
I have used the following and several other iterations to try and create this dynamically:
<script>
var listItem = [];
function createTestList() {
var tests = results.tests; //an array to tests to populate list
var i;
var j;
for (i = 0; i < tests.length ; i++ ){
listItem[i] = document.createElement("li");
var node = document.createTextNode(tests[i].name);
listItem[i].appendChild(node);
listItem[i].setAttribute("href", "#modal-one");
addOnClick(i);
//var element = document.getElementById("div1");
//element.appendChild(listItem[i]);
document.body.appendChild(listItem[i]);
console.log(listItem[i]);
};
};
function addOnClick(j) { //this is separate to handle the closure issue
listItem[j].onclick = function() {loadModal(j)};
};
</script>
However, this code (and several others) produce:
<li href='#modal-one'>Complete Blood Count</li> //note missing <a>...</a>
It appears there are several ways to achieve this, but nothing seems to work for me...
You are never actually adding in an anchor tag. You are creating a list-item (li), but you are adding an href to that list-item rather than adding an anchor node to it with that href. As such, the browser just thinks you have a list-item with an href attribute.
Consider using the following instead:
<script>
var listItem = [];
function createTestList() {
var tests = results.tests; //an array to tests to populate list
var i;
var j; // Never actually used in function. Consider omitting
for (i = 0; i < tests.length ; i++ ){
// create the list item
listItem[i] = document.createElement("li");
// Create the anchor with text
var anchor = document.createElement("a");
var node = document.createTextNode(tests[i].name);
anchor.appendChild(node);
anchor.setAttribute("href", "#modal-one");
// Set the onclick action
addOnClick(i, anchor);
// Add the anchor to the page
listItem[i].appendChild(anchor);
document.body.appendChild(listItem[i]);
console.log(listItem[i]);
};
};
// Modified "addOnClick" to include the anchor that needs the onclick
function addOnClick(j, anch) { //this is separate to handle the closure issue
anch.onclick = function() {loadModal(j)};
};
</script>
A couple things to note:
I have modified your addOnClick() function because it is the anchor element that needs the onclick, not the list item.
I have added in the creation of an anchor element rather than simply creating a list item and adding the href to that.
I do not see creating a element, change code to:
var aNode=document.createElement("a");
aNode.innerText=tests[i].name;
aNode.setAttribute("href", "#modal-one");
listItem[i].appendChild(aNode);
You can change also click method, to use it on a not on li
function addOnClick(j) {
listItem[j].querySelector("a").addEventListener("click",function(e) {
e.preventDefault();//this prevent for going to hash in href
loadModal(j);
});
};
Okay. I missed the anchor tag. My bad...
Spencer's answer came close, but I had to make few changes to get it work in my instance.
The final working code (and honestly I am not sure why it works) is:
<script>
var listItem = [];
function createTestList() {
var tests = results.tests;
var i;
//var j;
for (i = 0; i < tests.length ; i++ ){
// create the list item
listItem[i] = document.createElement("li");
// Create the anchor with text
var anchor = document.createElement("a");
anchor.setAttribute("href", "#modal-one");
var node = document.createTextNode(tests[i].name);
anchor.appendChild(node);
// Set the onclick action
addOnClick(i);
// Add the anchor to the page
listItem[i].appendChild(anchor);
document.getElementById("demo").appendChild(listItem[i]); //added the list to a separate <div> rather than body. It works fine like this.
console.log(listItem[i]);
};
};
function addOnClick(j) { //this is separate to handle the closure issue
//didn't need the additional code beyond this
listItem[j].onclick = function() {loadModal(j)};
};
</script>
Thanks to all and Spencer thanks for the thoroughly commented code. It helps!!!

Javascript Custom Alert Box with Image alignment

I Have created Custom Alert Box in Javascript . I Have added text with images. but It is not align proberly. It came some thing like this.
I am trying to add the correct mark and text with same line, how can I achieve this. can anyone please help me. I have added my Custom alert box Function below.
function createCustomAlert(txt, string_url,fd) {
// shortcut reference to the document object
d = document;
// if the modalContainer object already exists in the DOM, bail out.
if (d.getElementById("modalContainer")) return;
// create the modalContainer div as a child of the BODY element
mObj = d.getElementsByTagName("body")[0].appendChild(d.createElement("div"));
mObj.id = "modalContainer";
// make sure its as tall as it needs to be to overlay all the content on the page
mObj.style.height = document.documentElement.scrollHeight + "px";
// create the DIV that will be the alert
alertObj = mObj.appendChild(d.createElement("div"));
alertObj.id = "alertBox";
// MSIE doesnt treat position:fixed correctly, so this compensates for positioning the alert
if (d.all && !window.opera) alertObj.style.top = document.documentElement.scrollTop + "px";
// center the alert box
alertObj.style.left = (d.documentElement.scrollWidth - alertObj.offsetWidth) / 2 + "px";
// create an H1 element as the title bar
h1 = alertObj.appendChild(d.createElement("h1"));
h1.appendChild(d.createTextNode(ALERT_TITLE));
btn2 = alertObj.appendChild(d.createElement("img"));
btn2.id = "fd";
btn2.src = fd;
// create a paragraph element to contain the txt argument
msg = alertObj.appendChild(d.createElement("p"));
msg.innerHTML = txt;
// create an anchor element to use as the confirmation button.
//btn = alertObj.appendChild(d.createElement("a"));
//btn.id = "closeBtn";
//btn.appendChild(d.createTextNode(ALERT_BUTTON_TEXT));
//btn.href = "";
btn = alertObj.appendChild(d.createElement("img"));
btn.id = "closeBtn";
btn.src = 'new-go-next2.png';
btn.href="#ss";
//btn.height="30px";
//btn.width="30px";
//btn.href="#";
// set up the onclick event to remove the alert when the anchor is clicked
btn.onclick = function () { removeCustomAlert(); window.location = string_url; return false; }
}
well yes creating a table would be a great approach to solve your problems , btw u can also try some internal divs with proper position anf the element having correct float attribute
Rather creating div element create table with two Columns. First of which will contain 'Image' for OK and Second one will contain your 'Text'.
Check if this helps.

Categories

Resources