<div id = "first"></div>
<div id = "second"></div>
<div id = "third"></div>
Trying to dynamically append to these divs within a javascript function
if (condition??) variable = "first"
else if (condition) variable = "second"
else variable = "third"
let div = document.getElementById(variable);
Variable above could be first, second, or third depending on some condition.
div.appendChild(img)
div.appendChild(text)
However since div ends up being null I wont be able to append anything to it cuz of the following error.
Cannot read property 'appendChild' of null.
So any idea how to go around this?
Edit: Added the actual code snip below
// my html
<div id = "list" class = "center"> Listing <br><br>
<div id = "first"></div>
<div id = "second"></div>
<div id = "third"></div>
</div>
//my js
$.ajax({
async: true,
type: 'GET',
url: "rankings/" + boss + ".txt",
boss : boss,
success: function(sData){
let temp = this.boss
let div = document.getElementById(temp);
//console.log(temp) logs "first" on the console
let img = document.createElement("img");
let text = document.createElement('td1');
img.src = "images/" + temp + ".jpg";
img.alt = temp
div.appendChild(img)
div.appendChild(text)
Edit 2: Image of code exection
https://imgur.com/a/WkYTn
Your code looks correct! However, I think the problem is, you are loading the Javascript before the DOM is being rendered (Eg. you are loading the script in <head>). So javascript is not able to find the divs..
var variable= "second";
var boss = "boss_baby";
let div = document.getElementById(variable);
console.log(variable) //logs "first" on the console
let img = document.createElement("img");
let text = document.createElement('td1');
img.src = "images/" + boss + ".jpg";
img.alt = boss
div.appendChild(img)
div.appendChild(text)
#first, #second, #third {
display:block;
border: 1px solid blue;
height: 50px;
width: 200px;
margin : 10px;
}
<div id = "list" class = "center"> Listing <br><br>
<div id = "first"></div>
<div id = "second"></div>
<div id = "third"></div>
</div>
To solve this issue you can either load the <script> right before the body tag ends </body>
or add all your script in onload methods
window.onload = function() {
// all your JS code goes here
}
OR
document.onload = function() {
// all your JS code goes here
}
After question EDIT:
Your code looks correct! However, Now i suspect the element you are trying to access might have been removed by the time you get your response from ajax.
Try this Code Pen Example . I think your problem is with the "variable" and how your assigning value to it.
<div id = "first" style="border:1px red solid"></div>
<div id = "second" style="border:blue"></div>
<div id = "third" style="border:green"></div>
<script>
//try changing the value of condtion
var condition=3;
var variable="";
var img = document.createElement("img");
//var text = document.createElement('td1');
img.src = "https://www.w3schools.com/w3images/fjords.jpg";
img.alt = "boss"
//div.appendChild(img)
if (condition==1) variable = "first"
else if (condition==2) variable = "second"
else variable = "third"
console.log(img)
document.getElementById(variable).appendChild(img);
<script>
Related
I'm making a chat and I want to add an avatar pics feature so I figured it might work well with span, but the problem is I don't know how to add the span to the element.
let avatar = document.createElement("span");
let userMessage = document.createElement("H3");
avatar.setAttribute(userMessage);
userMessage.innerHTML = username + ": " + message;
//document.getElementById("chat").appendChild(avatar);
document.getElementById("chat").appendChild(userMessage);
userMessage.style.background = color;
userMessage.style.textAlign = "left";
document.getElementById("msg").value = "";
I am assuming that you have div with id="chat" and you want to append an h3 tag in a span and then append the chat div so your code will look like this
var username="zulqarnain jalil";
var message ="welcome back, have a nice day";
var color='lightgrey';
var avatar = document.createElement("span");
var userMessage = document.createElement("h3");
userMessage.innerHTML = username + ": " + message;
userMessage.style.background = color;
userMessage.style.textAlign = "left";
avatar.appendChild(userMessage);
document.getElementById("chat").appendChild(avatar);
//document.getElementById("msg").value = "";
<div id="chat">
</div>
I have created a chatbot snippet for you, here you can test it
var username="zulqarnain jalil";
function sendMessage()
{
var message =document.getElementById('messagebox').value;
if(message)
{
document.getElementById('messagebox').value='';
var color='lightgrey';
var avatar = document.createElement("span");
var userMessage = document.createElement("h3");
userMessage.innerHTML = username + ": " + message;
userMessage.style.background = color;
userMessage.style.textAlign = "left";
avatar.appendChild(userMessage);
document.getElementById("chat").appendChild(avatar);
}
else
{
// message empty
}
}
//document.getElementById("msg").value = "";
<div id="chatBox">
<div id="chat">
</div>
<div>
<input type="text" id="messagebox" />
<input type="button" onclick="sendMessage()" value="Send" />
</div>
</div>
First you need to add the span as a child of the H3 element.
I think the best approach to this problem is creating a class Message. Initializing that class creates h3 and span with unique ids stored in a variable id for future use. The class will also add the h3 as a child of it's parent element ( what ever it is ), and the span as a child of the h3 element.
var counterText = 0;
var counterAvatar = 0;
class UserMessage {
constructor(msgTxt, avatar){
// This block initializes the text message of the user
// It will also add an id to the tag for future use
let msgTxt = document.createTextNode(msgTxt);
this.messageID = 'text' + counterText;
this.message = document.createElement('h3');
this.message.appendChild(msgTxt);
this.message.setAttribute('id', this.messageID);
counterText++;
// This block creates an img element with the attributes src and id
this.avatarID = 'avatar' + counterAvatar;
this.avatar = document.createElement('img');
this.avatar.setAttribute('src', avatar);
this.avatar.setAttribute('id', this.avatarID);
counterAvatar++;
// This block appends the avatar element to the text and the text to the
// chat div.
let chat = document.getElementById('chat');
this.message.appendChild(this.avatar);
chat.appendChild(this.message);
}
}
to initialize a new instance:
var message = new UserMessage("Hello, this is a text message!",'<path/to/avatar>')
this is an object oriented aproach.
you could also just append the avatar to the message and the message to the chat.
But I think aproaching the problem in an object oriented way is much better since it will save time in the future when you're updating your app.
Markdown works fine in here.
Block-level HTML elements have a few restrictions:
They must be separated from surrounding text by blank lines.
The begin and end tags of the outermost block element must not be indented.
Markdown can't be used within HTML blocks.
I'm having a strange problem. I'm trying to make a program that will add and delete div's inside another div called "body". To add divs, I use document.getElementById("body").innerHTML. Adding works fine. However, in the deleting function, I replace the "body" id with a variable with the id of the div that will be deleted. But when I run the code, I get the error "cannot set innerHTML of null". I tried to replace the id variable with a fixed local variable, and it worked fine. I also tried to add quotes to the variable but that didn't work either. Is there any reason why I can't set the id to a changing variable? Thanks.
Here is my code:
var i = 1;
function myFunction() {
var addDiv = document.getElementById("body2");
addDiv.innerHTML += "<div id = '" + i + "'><br><textarea id = '1' > foo < /textarea></div > ";
i++;
}
function myFunction2() {
var deleteDiv = document.getElementById(i);
deleteDiv.innerHTML = "";
i--;
}
<div id="body2">
<div id="0">
<textarea id="text">lol</textarea><button onclick="myFunction()">Add</button>
<button onclick="myFunction2()">Delete</button>
</div>
</div>
you are incrementing i after adding a div so you must use i-1 while deleting to get correct id.
var i = 1;
function myFunction() {
var addDiv = document.getElementById("body2");
addDiv.innerHTML += "<div id = '"+i+"'><br><textarea id = '1'>foo</textarea></div>";
i++;
}
function myFunction2() {
var deleteDiv = document.getElementById(i-1);
deleteDiv.remove();
i--;
}
<div id = "body2">
<div id = "0">
<textarea id = "text">lol</textarea><button onclick =
"myFunction()">Add</button>
<button onclick = "myFunction2()">Delete</button>
</div>
</div>
To remove last child, you can even use CSS selector last-child. You should also add specific class to newly added divs as you would want to remove only newly added divs.
This will also remove dependency of i.
As an addon, you can also use document.createElement + Node.appendChild instead of setting innerHTML. .innerHTMl will be expensive for highly nested structure.
function myFunction() {
document.getElementById("body2").appendChild(getDiv());
}
function getDiv(i){
var div = document.createElement('div');
div.classList.add('inner')
var ta = document.createElement('textarea');
ta.textContent = 'foo';
div.appendChild(ta);
return div;
}
function myFunction2() {
var div = document.querySelector('#body2 div.inner:last-child')
div && div.remove()
}
<div id="body2">
<div id="0">
<textarea id="text">lol</textarea><button onclick="myFunction()">Add</button>
<button onclick="myFunction2()">Delete</button>
</div>
</div>
You can refer "innerHTML += ..." vs "appendChild(txtNode)" for more information.
I am trying to refactor old code without completely redoing the program.
I have objects that are strategically named to be a value of the string from vendor. (vendor = "Ansys" or vendor = "Cadence")
var Ansys = {key:'ansyskeys', loaded:0, display: "none", otherkey: 'anotherkey'};
var Cadence = {key:"cdskeys", loaded:0, display: "none", otherkey: 'cotherkey'};
My previous HTML code that was static and had many entries that looked like:
<div id="ansyskeys" style="display:none">
<select id="anotherkey" size="5" onchange="selectOther('anotherkey')"></select>
</div>
To replace this, I made a function -ignore the use of eval, security is no concern:
function createDiv()
{
var vendorKey = eval(vendor).key;
var otherVendorKey = eval(vendor).otherkey;
var myDiv = document.createElement('div');
var html = '<select id="' + otherVendorKey + '" size="4" onchange="selectOther('+ otherVendorKey + ')"></select>';
myDiv.innerHTML = html;
myDiv.id = vendorKey;
document.body.appendChild(myDiv);
}
I am recieving my desired result, however, when I try to use selectedIndex in the function selectOther, it appears that mk is null.
function selectOther(wid)
{
var mk = document.getElementById(wid);
alert(mk);
var index = mk.selectedIndex;
key = mk.options[index].value;
setKey ();
getKeyStats ();
}
The HTML seems to be working, but doesnt seem to recognize the id from wid. Any help would be much appreciated.
I'm trying to learn HTML and Javascript/jQuery. If I have a container which holds a title, an image, a description and a number, then I want to create a new container with the exact same format (except the values will be different), how is this commonly done?
This is an example of the format I'm looking for in each item.
<li>
<div>
<div>
Image Name
</div>
<div>
<a href=URL>
<img src='image_url'>
</a>
</div>
<div>
Description
</div>
<div>
num_comment Comments
</div>
</div>
</li>
Do I just create a string and concatenate with the actual values for the image, then add that string to some variable I've saved called html_content, and then set the html value to html_content? Is that the common way of doing this or is there a better way?
EDIT
To give a better idea of what I'm currently doing, here's the javascript:
var html1 = '<li><div><div>';
var html2 = '</div><div><a href="';
var html3 = '"><img src="';
var html4 = '"></a></div><div>';
var html5 = '</div><div>';
var html6 = '</div></div></li>';
function render(pics){
for (var i in pics){
html = html + html1 + pics[i].name + html2 + pics[i].image_url + html3 + ...
};
$('pics').html(html);
}
In jQuery you just have to use the append() function to add on to something.
You could do something like...
$('select element').append('<li><div>....etc.');
and where you want a different value you can use a variable.
You can use .clone() and create a copy of this, then iterate through the cloned object and change what you need:
var $objClone = $("li").clone(true);
$objClone.find("*").each(function() {
//iterates over every element. customize this to find elements you need.
});
To change the image source you can do:
$objClone.find("img").attr("src", "new/img/here.jpg");
Fiddle demoing the concept: http://jsfiddle.net/H9DnA/1/
You may find it useful to explore some of the JavaScript templating libraries. The essential idea is that you create a template of your markup:
<li>
<div>
<div>
{{name}}
</div>
<div>
<a href="{{url}}">
<img src="{{imageUrl}}">
</a>
</div>
<div>
{{description}}
</div>
<div>
{{comments}}
</div>
</div>
</li>
Then you merge it against some associated matching object and insert it into your document:
{ name: 'Image Name',
url: 'http://example.com',
imageUrl: 'http://example.com/image.jpg',
description: 'Description',
comments [ { text: 'Comment' } ]
}
function render(pics)
{
var theList = document.getElementByid("LIST ID");
for (var i in pics){
var listItem = document.createElement('li'); // Create new list item
var nameDiv = document.createElement('div'); // Create name DIV element
nameDiv.innerHTML = pics[i].name; // Insert the name in the div
var img = document.createElement('img'); // Create Img element
img.setAttribute('src',pics[i].src); // Assign the src attribute of your img
var imgDiv = document.createElement('div'); // Create Img Div that contains your img
imgDiv.appendChild(img); // Puts img inside the img DIV container
var descDiv = document.createElement('div'); // Create Description DIV
descDiv.innerHTML = pics[i].description; // Insert your description
listItem.appendChild(nameDiv); // Insert all of you DIVs
listItem.appendChild(imgDiv); // inside your list item
listItem.appendChild(descDiv); // with appropriate order.
theList.appendChild(listItem); // Insert the list item inside your list.
}
}
I think this will work just fine:
$('#button').click(function () {
var html1 = '<li><div><div>';
var html2 = '</div><div><a href="';
var html3 = '"><img src="';
var html4 = '"></a></div><div>';
var html5 = '</div><div>';
var html6 = '</div></div></li>';
function render(pics){
for (var i in pics){
html = html + html1 + pics[i].name + html2 + pics[i].image_url + html3 + ...
$("ul").append(html);
}
}
// call render
});
I didn't do a test run on your code so there might be an error somewhere. My tweak adds this line $("ul").append(html); inside your loop
I'm trying to get this JavaScript working:
I have an HTML email which links to this page which contains a variable in the link (index.html?content=email1). The JavaScript should replace the DIV content depending on what the variable for 'content' is.
<!-- ORIGINAL DIV -->
<div id="Email">
</div>
<!-- DIV replacement function -->
<script type="text/javascript">
function ReplaceContentInContainer(id,content) {
var container = document.getElementById(id);
container.innerHTML = content;
}
</script>
<!-- Email 1 Content -->
<script ="text/javascript">
var content = '<div class="test">Email 1 content</div>';
ReplaceContentInContainer('Email1',content);
}
</script>
<!-- Email 2 Content -->
<script ="text/javascript">
var content = '<div class="test">Email 2 content</div>';
ReplaceContentInContainer('Email2',content);
}
</script>
Any ideas what I've done wrong that is causing it not to work?
Rather than inserting the element as text into innerHTML create a DOM element, and append it manually like so:
var obj = document.createElement("div");
obj.innerText = "Email 2 content";
obj.className = "test"
document.getElementById("email").appendChild(obj);
See this working here: http://jsfiddle.net/BE8Xa/1/
EDIT
Interesting reading to help you decide if you want to use innerHTML or appendChild:
"innerHTML += ..." vs "appendChild(txtNode)"
The ReplaceContentInContainer calls specify ID's which are not present, the only ID is Email and also, how are the two scripts called, if they are in the same apge like in the example the second (with a corrected ID) would always overwrite the first and also you declare the content variable twice which is not permitted, multiple script blocks in a page share the same global namespace so any global variables has to be named uniquely.
David's on the money as to why your DOM script isn't working: there's only an 'Email' id out there, but you're referencing 'Email1' and 'Email2'.
As for grabbing the content parameter from the query string:
var content = (location.search.split(/&*content=/)[1] || '').split(/&/)[0];
I noticed you are putting a closing "}" after you call "ReplaceContentInContainer". I don't know if that is your complete problem but it would definitely cause the javascript not to parse correctly. Remove the closing "}".
With the closing "}", you are closing a block of code you never opened.
First of all, parse the query string data to find the desired content to show. To achieve this, add this function to your page:
<script type="text/javascript">
function ParseQueryString() {
var result = new Array();
var strQS = window.location.href;
var index = strQS.indexOf("?");
if (index > 0) {
var temp = strQS.split("?");
var arrData = temp[1].split("&");
for (var i = 0; i < arrData.length; i++) {
temp = arrData[i].split("=");
var key = temp[0];
var value = temp.length > 0 ? temp[1] : "";
result[key] = value;
}
}
return result;
}
</script>
Second step, have all possible DIV elements in the page, initially hidden using display: none; CSS, like this:
<div id="Email1" style="display: none;">Email 1 Content</div>
<div id="Email2" style="display: none;">Email 2 Content</div>
...
Third and final step, in the page load (after all DIV elements are loaded including the placeholder) read the query string, and if content is given, put the contents of the desired DIV into the "main" div.. here is the required code:
window.onload = function WindowLoad() {
var QS = ParseQueryString();
var contentId = QS["content"];
if (contentId) {
var source = document.getElementById(contentId);
if (source) {
var target = document.getElementById("Email");
target.innerHTML = source.innerHTML;
}
}
}
How about this? Hacky but works...
<!-- ORIGINAL DIV -->
<div id="Email"></div>
<script type="text/javascript">
function ReplaceContentInContainer(id,content) {
var container = document.getElementById(id);
var txt = document.createTextNode(content);
container.appendChild(txt);
}
window.onload = function() {
var args = document.location.search.substr(1, document.location.search.length).split('&');
var key_value = args[0].split('=');
ReplaceContentInContainer('Email', key_value[1]);
}
</script>