Okay, so I searched and could not really find an answer for this. I am creating a Javascript function that will easily add an element to the specified element. Here is the syntax:
function add(element, to, idName, className) {
//creates new element for DOM
var newElement = document.createElement(element);
//sets ID attribute for element
var attrId = newElement.createAttribute('id');
attrId.value = idName;
//sets class attribute
var attrClass = newElement.createAttribute('class');
attrClass.value = className;
document.getElementById(to).appendChild(newElement);
}
Long story short, it doesn't work. Yes, my JS is linked fine to my HTML and I have already used many other functions in the same JS file, but this is the one I am having trouble on. I am sure there is some form of a syntax error but can't seem to find it.
P.S. This is my first time using JS to dynamically add a page element without changing innerHTML directly.
The problem is that the id and class are already defined in each element.
To access an element's id, just do element.id = id. As for the classes, there's a thing called element.classList, and if you want to add a class just type element.classList.add("class_name"), and to remove it type element.classList.remove("class_name").
The correct code now comes as:
function add(element, to, idName, className) {
//creates new element for DOM
var newElement = document.createElement(element);
//sets ID attribute for element
newElement.id = idName;
//sets class attribute
newElement.classList.add(className);
document.getElementById(to).appendChild(newElement);
}
check this documentation to understand more about classLists
There's no reason to use .createAttribute() here. You're creating those attributes, but doing nothing to associate them with the element you're creating. Things are much simpler than that:
function add(element, to, idName, className) {
//creates new element for DOM
var newElement = document.createElement(element);
//sets ID attribute for element
newElement.id = id;
//sets class attribute
newElement.className = className;
document.getElementById(to).appendChild(newElement);
}
Note that you're probably going to want to work on the fact that you sometimes need more than just a tag name, id, and class. <input> elements are a good example — they require a "type" attribute (well, not really require, but an API like this would need to account for that.)
Related
I'm trying to get all classes from one element, then add them to another element created dynamically. I was originally stuck on how to do this, but as I was typing out this question, I worked out a solution. However, it seems a bit verbose. Is there a way to do this same thing more efficiently, i.e. with fewer lines of code?
let classes = this.nextElementSibling.classList; // get classes from target element
classes += ''; // convert classlist object to string
let class_array = classes.split(' '); // convert string to array
const my_div = document.createElement('div'); // create a new div
for(i=0; i<class_array.length; i++) { // loop through array and add classes to the div
my_div.classList.add(class_array[i]);
}
Thanks in advance.
The className will give you a space-separated string of class names an element has. Just use that.
const my_div = document.createElement('div');
my_div.className = this.nextElementSibling.className;
In my program I am dynamically creating feedback boxes to respond to user input. My problem is, I don't know how many of these pieces of feedback will be outputted. I have created a function in my javascript that assigns an id to each new element I create at runtime by concatenating a string with a variable number - which is incremented after every time the constructor is called - and appending it to my CSS class for styling, however I'm not sure how to reference a varying id in my html so that they actually appear on the screen.
var counter = 0;
function constructFeedbackBox() {
counter++;
var newElement = 'toast' + counter;
var i = null;
i = document.createElement('div');
i.id = newElement;
i.className = ".toastStyle";
}
In addition, if there are any problems with the way I've done my javascript to create my Id and/or append it to my class, the info would be much appreciated (I'm still pretty new to this)
First of all, document.createElement() takes a tagName as an input. If you are making divs, your line should read document.createElement('div');.
You can then do i.setAttribute(id, 'toast' + counter);.
What are you trying to accomplish overall with this? Maybe there is a better approach. Also worth noting that IDs must be unique, so be careful about that.
I want to find with Javascript an element by class name. This class is unique. I try to do this with
var element = document.getElementByClassName('uniqueclass')
This element have two classes (uniqueclass and element-x). I want to get the other class and work with this class as String. I tried this with various functions (classname.split, ...), but I don't find a solution.
Can anybody help me? Thanks!
You can fetch the node, retrieve the classList of the node and filter them by your term:
var uniqueClassName = 'unique'; // What is your unique className?
var element = document.querySelector('.' + uniqueClassName); // Fetch the element
var filterClassList = function (class) {
return class !== uniqueClassName; // Differs the className from the unique one?
};
var classList = element.classList.filter(filterClassList); // Filter the classList via filter function
You are doing it in right way.
Few changes
element = document.getElementsByClassName('uniqueclass')[0];
It is Elements not Element and it return a HTML Collection. Since this class name is unique, use index [0].
To get other classses of this element,
class = element.getAttribute('class');
Now class contains "uniqueclass element-x"
I created a constructor that will handle a custom list control. I created a method in order to allow the user to add elements to the list, and I need to assign event handlers to the click events of the list elements (divs).
A simplified version of the code is here. The list elements are created using the innerHTML property and a string template upon which I substitute specific parts. Later I get the element by it's id and assign it a function in closure:
function prueba(){
var plantilla = '<div id="«id»">«texto»</div>';
var f = function(nombre){
return function(){console.log('mi nombre es ' + nombre)};
};
this.agregar = function(id, texto){
var tmp = plantilla.replace('«id»', id);
tmp = tmp.replace('«texto»', texto);
document.body.innerHTML += tmp;
document.getElementById(id).onclick = f(id);
};
};
The problem is that, apparently, the event handler is unasigned to previous created divs, so is only retained by the last one, as it can be tested with the following code:
var p = new prueba;
p.agregar('i1', 'texto1');
console.log(document.getElementById('i1').onclick.toString());//shows the function code
p.agregar('i2', 'texto2');
console.log(document.getElementById('i2').onclick.toString());//shows the function code
console.log(document.getElementById('i1').onclick.toString());//returns 'null' error
p.agregar('i3', 'texto3');
console.log(document.getElementById('i3').onclick.toString());//shows the function code
console.log(document.getElementById('i2').onclick.toString());//returns 'null' error
This happens in Iceweasel as well as in Chromium. It does NOT happen when I add 'onclick = f(«id»)' in the template (which I cannot do here because of the assigned function scope), and neither happens if I use document.createElement. What am I doing wrong?
You destroy elements previously created when you do this:
document.body.innerHTML += tmp;
Instead use insertAdjacentHMTL() if you want to append using HTML markup.
document.body.insertAdjacentHTML("beforeend", tmp);
Now instead of going through this destructive process...
serialize the existing DOM nodes to HTML
concatenate the new HTML fragment to the serialized nodes
destroy the old nodes
recreate the nodes with the new nodes
...it simply creates the new content and places it before the close of the body element.
Basically, remove element.innerHTML += ... from your coding practices. It's never necessary, it's inefficient and it causes problems like what you've described.
FYI, the .insertAdjacentHTML() method receives 4 different string possibilities as the first argument. Each one designates a position relative to the element on which you're calling it.
The strings are...
"beforebegin"
"afterbegin"
"beforeend"
"afterend"
The labels are pretty self-explanatory. They position the new content before the current element, inside the current element at the beginning, inside the current element at the end, or after the current element, respectively.
Your full code will look like this, which I shortened a bit too since the tmp really isn't needed here:
function prueba(){
var plantilla = '<div id="«id»">«texto»</div>';
var f = function(nombre){
return function(){console.log('mi nombre es ' + nombre)};
};
this.agregar = function(id, texto){
document.body.insertAdjacentHTML("beforeend",
plantilla.replace('«id»', id)
.replace('«texto»', texto));
document.getElementById(id).onclick = f(id);
};
};
I am trying to add to all <object>'s on a page a snippet of html. I understand I can access elements by tag name and that I can change the element, but can I simple append to it instead?
In addition, I want to add it to the contents of each tag, not the end of the document. Which of these methods will work?
Assuming no library...
var elementToAppend = document.createElement(tagName); // Your tag name here
// Set attributes and properties on elementToAppend here with
// elementToAppend.attribute = value (eg elementToAppend.id = "some_id")
// You can then append child text and elements with DOM methods
// (createElement or createTextNode with appendChild)
// or with innerHTML (elementToAppend.innerHTML = "some html string")
var objects = document.getElementsByTagName('object');
for(var i = 0; i < objects.length; i++) {
elementToAppend = elementToAppend.cloneNode(true);
objects[i].appendChild(elementToAppend);
}
Using innerHTML or outerHTML as other answers have suggested will likely cause problems for whatever you've embedded with <object>.
appendChild is what you're looking for.