Issue with getElementById and similar calls on dynamically created elements - javascript

Uncaught TypeError: Cannot read property 'style' of null
No matter what I've tried I cannot get any of the javascript methods to identify each individual div created with unique IDs. Does anyone see where I'm messing up the call to find the div with specified ID and update it's css styling?
I also cannot seem to dynamically create an object with an onclick event to toggle what details are shown. I've tried to create individual buttons with an on-click event for the above event but can't get it to stick unless I hard code a button in rather than dynamically creating it.
without the last function included everything runs as expected and each div has a unique id but with the last function the program breaks before any of the elements can be created.
Javascript
function createTable() {
var list = document.querySelector('#table')
var toAdd = document.createDocumentFragment();
var id = '0';
for(var i = 0; i < 7; i++) {
var identifier = document.createElement('div');
identifier.id = id;
identifier.className = 'item';
identifier.innerHTML = standards[i].identifier;
toAdd.appendChild(identifier);
id++;
var description = document.createElement('div');
description.id = id;
description.className = 'description';
description.innerHTML = standards[i].statement;
var extended = document.createElement('div');
extended.id = 'r' + i;
extended.className = 'standard extra';
extended.innerHTML = standards[i].description;
description.appendChild(extended);
toAdd.appendChild(description);
id++;
var subconcept = document.createElement('div');
subconcept.id = id;
subconcept.className = 'subitem';
subconcept.innerHTML = standards[i].subconcept;
toAdd.appendChild(subconcept);
id++
var practices = document.createElement('div');
practices.id = id;
practices.className = 'subitem';
practices.innerHTML = standards[i].practices;
toAdd.appendChild(practices);
id++;
var link = document.createElement('p');
link.className = 'link';
link.innerHTML = "more...";
link.onclick = displaySubinfo(id);
toAdd.appendChild(link);
}
list.appendChild(toAdd);
}
function displaySubinfo(id) {
var elem = document.getElementById(id);
elem.style.display = "inline";
elem = document.getElementById(id - 1);
elem.style.display = "inline";
}
HTML
<!DOCTYPE html>
<html>
<head>
<link href="site.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title class="page-title">Computer Science Standards</title>
</head>
<body>
<script src="standards.js"></script>
<script src="site.js"></script>
<div id="table">
<div class="column-name">
Identifier
</div>
<div class="column-name">
Standard
</div>
<div class="column-name">
Subconcept
</div>
<div class="column-name">
Practices
</div>
<script>createTable()</script>
</div>
<script>
</script>
</body>
</html>

This part won't work:
link.onclick = displaySubinfo(id);
what that does is call the displaySubinfo function right away, and assign the return value (undefined) to the onclick event.
It seems that you wouldn't need any of the IDs if the displaySubInfo function was able to work without parameters, so:
function displaySubinfo(e) {
// get the element that was clicked
var elem = e.target;
elem.style.display = "inline";
// also change the previous element
var prev = elem.previousElementSibling;
prev.style.display = "inline";
}
What the heck's e? Event object containing useful stuff like the element that was clicked. We get that for free if we wire up your function like this:
var link = document.createElement('p');
link.className = 'link';
link.innerHTML = "more...";
link.addEventListener("click", displaySubinfo);

Related

How to access elements that were created in script?

In the function below, I create cards that have a toggle button and remove button. However, when I try to access the buttons with a queryselector, I get null. Anyone know how to access elements that were created in a different file? I can provide the full files if needed.
function updateDisplay() {
for (i = 0; i < myLibrary.length; i++){
let div = document.createElement('div');
let title = document.createElement('h5');
let author = document.createElement('h5');
let pages = document.createElement('h5');
let isRead = document.createElement('h5');
let removeButton = document.createElement('button');
let toggleButton = document.createElement('button');
div.classList.add('card');
title.classList.add('title');
author.classList.add('author');
pages.classList.add('pages');
isRead.classList.add('isRead');
removeButton.classList.add('removeButton');
toggleButton.classList.add('toggleButton');
title.textContent = myLibrary[i].title;
author.textContent = myLibrary[i].author;
pages.textContent = `${myLibrary[i].pages} pages`;
isRead.textContent = myLibrary[i].isRead ? 'Read' : 'Unread';
removeButton.textContent = 'Remove';
toggleButton.textContent = 'Toggle Read Status';
Your problem is obvious you're creating the elements but not appending the into the body.
you'll have to append each element you create like the following example:
var element= document.createElement("div"); // Create a <div> element
element.innerHTML = "some content"; // Insert text
document.body.appendChild(element); // Append <div> to <body>
note that you can do document.body.append(div,title,author,pages,isRead,removeButton,toggleButton);
to append them all in one line

How to dynamically add remove block using javascript

I am facing a problem while removing a paragraph, which I have added using javascript.
Adding buttons work fine. The problem occurs when I try to remove the paragraph.
function rdn_id(){return Math.random().toString(36).substring(7);}
//create button
function create_btn()
{
//Create a remove button
var btn_remove = document.createElement("BUTTON");
//create a unique button ID
id_btn_remove = rdn_id();
btn_remove.id = id_btn_remove ;
btn_remove.textContent = "Remove file";
return [btn_remove, id_btn_remove];
}
//add elt function
function create_p_btn()
{
//Create paragraph
var paragraph = document.createElement("P");
//create a unique p ID
id_paragraph = rdn_id();
paragraph.id = id_paragraph;
paragraph.style.paddingTop = "5px";
paragraph.style.background = "blue";
document.getElementById("setItHere").appendChild(paragraph);
// add button
var values = create_btn();
var btn_rmv = values[0];
var id_btn = values[1];
paragraph.appendChild(btn_rmv);
document.getElementById(id_btn).addEventListener("onclick", function(){remove_func(id_paragraph);});
}
//Remove function
function remove_func(id_el)
{
var elt = document.getElementById(id_el);
elt.parentNode.removeChild(id_el);
}
<div id="setItHere">
<Button id="start" onclick="create_p_btn();">add</Button>
</div>
Am I missing something ?
Thank you in advance.
You need to make two changes:
Event name should be click instead of onclick
elt.parentNode.removeChild(id_el); should be elt.parentNode.removeChild(elt);
Check out this pen
https://codepen.io/tanmayv/pen/yLNwNNJ

How to hide child elements using javascript

<div id="wpq2">
<div class="subClass">
<a id="linkTO" class="subClass">New Item</a>
or
<a class="subClass">edit</a>
this list
</div>
</div>
i want to hide all the thing except
<a id="linkTO" class="subClass">New Item</a>
I do not have access to html ,
i have to use javascript
i tried somthing
var parentID = document.getElementById('wpq2');
var sub = parentID.getElementsByClassName('subClass');
var lastChild = sub[0].lastChild;
lastChild.style.display = 'none';
Using javascript no idea how to do
Please suggest
Try this instead:
var parentID = document.getElementById('wpq2');
//get the first inner DIV which contains all the a elements
var innerDiv = parentID.getElementsByClassName('subClass')[0];
//get all the a elements
var subs = innerDiv.getElementsByClassName('subClass');
//This will hide all matching elements except the first one
for(var i = 1; i < subs.length; i++){
var a = subs[i];
a.style.display = 'none';
}
Here is a working example
EDIT: The above will only hide the a element, as your text elements are not contained within specific elements then it becomes more tricky. If you are happy to effectively "delete" the HTML you don't want then you can do the following:
var parentID = document.getElementById('wpq2');
//get the first inner DIV which contains all the a elements
var innerDiv = parentID.getElementsByClassName('subClass')[0];
//get the HTML for the a element to keep
var a = innerDiv.getElementsByClassName('subClass')[0].outerHTML;
//replace the HTML contents of the inner DIV with the element to keep
innerDiv.innerHTML = a;
Here is an example
insert new html if you don't need the rest
document.getElementById('wpq2').innerHTML = '<a id="linkTO" class="subClass">New Item</a>';
var parentID = document.getElementById('wpq2');
var innerDiv = parentID.getElementsByClassName('subClass')[0];
var subs = innerDiv.getElementsByClassName('subClass');
subs.forEach(function (sub) { sub.style.display = 'none'; });
document.getElementById("linkTO").style.display = 'block';

Change the onClick function to target the edit buttons

I have the following script
var counter = 0;
function appendText(){
var text = document.getElementById('usertext').value;
if ( document.getElementById('usertext').value ){
var div = document.createElement('div');
div.className = 'divex';
var li = document.createElement('li');
li.setAttribute('id', 'list');
div.appendChild(li);
var texty = document.createTextNode(text);
var bigdiv = document.getElementById('addedText');
var editbutton = document.createElement('BUTTON');
editbutton.setAttribute('id', 'button_click');
var buttontext = document.createTextNode('Edit');
editbutton.appendChild(buttontext);
bigdiv.appendChild(li).appendChild(texty);
bigdiv.appendChild(li).appendChild(editbutton);
document.getElementById('button_click').setAttribute('onClick', makeAreaEditable());
document.getElementById('usertext').value = "";
counter++;
}
};
var makeAreaEditable = function(){
alert('Hello world!');
};
I want the makeAreaeditable function to work when the Edit button is pressed(for each of the edit buttons that are appended under the textarea).. In this state, the script, alerts me when i hit the Addtext button.
the following is the html. P.S. i need this in pure javascript, if you can help. thanks
<textarea id="usertext"></textarea>
<button onClick="appendText()">Add text </button>
<div id="addedText" style="float:left">
</div>
instead of:
document.getElementById('button_click').setAttribute('onClick', makeAreaEditable());
you need to do this:
editbutton.onclick = makeAreaEditable;
the function's name goes without brackets unless you want to execute it
instead of obtaining the element from the DOM using document.getElementById('button_click')
you can use the editbutton variable already created. this object is the DOM element you are looking for
SIDE NOTE:
the standard way to do it is to add the onclick property before appending the element

JavaScript changing on click

I'd like some help changing this JavaScript onclick event to just load the data on page the page load...
Preferably not using the body on load tag...
So obviously I'd pre-set the var for term inside the script term rather than the existing on click event..
Hope that made sense.
<p><a id="keywordlink" href="?term=wombats">Get keywords for wombats</a></p>
<script type="text/javascript" src="keywords.js"></script>
<script type="text/javascript">
var x = document.getElementById('keywordlink');
if(x){
x.onclick = function(){
var term = this.href.split('=')[1];
this.innerHTML += ' (loading...)';
KEYWORDS.get(term,seed);
return false;
}
}
function seed(o){
var div = document.createElement('div');
var head = document.createElement('h2');
head.innerHTML = 'Keywords for '+o.term;
div.appendChild(head);
var p = document.createElement('p');
p.innerHTML = o.toplist;
div.appendChild(p);
var head = document.createElement('h3');
head.innerHTML = 'Details:';
div.appendChild(head);
var list = document.createElement('ol');
for(var i=0,j=o.keywords.length;i<j;i++){
var li = document.createElement('li');
li.innerHTML = o.keywords[i].term + '('+o.keywords[i].amount+')';
list.appendChild(li);
}
div.appendChild(list);
x.parentNode.replaceChild(div,x);
}
</script>
change this:
if(x){
x.onclick = function(){
var term = this.href.split('=')[1];
this.innerHTML += ' (loading...)';
KEYWORDS.get(term,seed);
return false;
}
}
to something like this:
function loadSomething(){
var term = x.href.split('=')[1];
x.innerHTML += ' (loading...)';
KEYWORDS.get(term,seed);
return false;
}
loadSomething();
you can leave it where it is, but for readability, put it below the seed function.
You should use something like onload or document.ready, but alternatively you can move the whole script file to the bottom of the page
Don't set the event handlers that way. Use addEventListener and (for IE) attachEvent.

Categories