What is the difference between these two ways to create an element? - javascript

var a = document.createElement('div');
a.id = "myDiv";
and
var a = document.createElement('div').id = "myDiv";
What is the difference between them such that the first one works and the second one doesn't?

Setting the id of the element does not return the element. It returns "myDiv" actually, so the var a is getting set to "myDiv" instead of the div itself.

The second one doesn't work because the "return" value from createElement is used to set the id. As that's an assignment and not chaining, it doesn't return the reference to the new element back to "a" and thus fails.

The second doesn't work as you're creating an element but immediately performing an operation upon it. The a variable is set to the string "myDiv" instead.

foo = 'bar' as a statement actually returns a value, which is 'bar'.
a = document.createElement('div'); //this sets `a` to DOM Node
a = document.createElement('div').id = 'myDiv'; //this sets `a` to 'myDiv'
//it's the same as
document.createElement('div').id = 'myDiv';
a = 'myDiv';
Don't ever do this
If you wanted to set both the ID and the a variable in one line, you could use parens:
(a = document.createElement('div')).id = 'myDiv';
That's because a = document.createElement('div') retuns the newly created DOM Node.

If you really want a short way, you can write :
(window.a=document.createElement('div')).id="myDiv";
Fiddle : http://jsfiddle.net/F23cD/

In the first statement you put the created element of type "div" into variable "a", and then set the element property "id" of "a" to "myDiv". Then "a" is now the element.
In the second statement you:
create the element of type "div": document.createElement('div')
set the element property "id" to "myDiv" and
set "a" to "myDiv" also
Then, "a" is now "myDiv" and not the element.

// use this
a.setAttribute("id","myDiv");

Related

Javascript element object not referencing DOM Input element

I am creating an HTML input element in JS, then inserting it into the DOM. However, after it is inserted, the JS element object does not reference the new DOM element.
The element type button element and input type 'submit' work too, but the input element seems to not work with either 'number' or 'text,' which I would be using.
let parent = document.createElement('div');
let child = document.createElement('div');
let childInput = document.createElement('input');
childInput.type = 'text';
childInput.value = 'foobar';
child.append(childInput);
parent.append(child);
document.body.append(parent);
There are no errors, however in chrome dev tools I can see the JS element object is not tied to the DOM object for the input when type is set to text or number. The element IS inserted into the DOM, however it does not reflect the JS object reference, and the value is not inserted into the DOM element, nor would the class, id, etc.
Edit: Also, it does not work when using the appendChild function either.
It sounds like you are trying to change the HTML attributes by setting the JavaScript properties, which doesn't always work. You can use myElement.setAttribute(attributeName, newValue) to change the HTML attributes using JavaScript (and myElement.propertyName = newValue to change the JavaScript properties.)
Note that the initial value of the value attribute is reflected in the defaultValue property. (There are a few other oddball property names like this where reserved words in JS conflict with HTML terms.)
Note also that HTML attributes are case-insensitive, whereas JS properties are case-sensitive -- and kebab-case attributes get mapped to camelCase properties.
Much more info on this can be found here: https://javascript.info/dom-attributes-and-properties
let parent = document.createElement('div');
let child = document.createElement('div');
let childInput = document.createElement('input');
childInput.type = 'text';
childInput.id = 'initialId';
childInput.classList.add('someClass');
childInput.defaultValue = 'initial value';
child.append(childInput);
parent.append(child);
document.body.append(parent);
// Initial attributes
let insertedChild = document.getElementById('initialId');
console.log(insertedChild.outerHTML);
// Modified attributes
insertedChild.setAttribute('id', 'changedId');
console.log("`id` property (reflected from attribute): " + insertedChild.id);
insertedChild.setAttribute('value', 'changedValue');
console.log("`value` property (reflected from attribute): " + insertedChild.value);
console.log(insertedChild.outerHTML);

setAttribute() doesn't "remember" the value assigned to it's ID in a function if its a defined variable?

This function creates a unique label and corresponding delete button on the screen that, when pressed, deletes itself and the label by its unique ID. In order to be able to distinguish itself from other label-delete pairs it is assigned a unique ID based on the selection that caused its existence (from a select menu).
function saveSelection(selection) {
var element = document.getElementById("div1");
var del = document.createElement("button");
del.type = "button";
del.id = selection;
del.setAttribute("onclick", "deleteSelection(selection)");
del.appendChild(document.createTextNode("delete"));
element.appendChild(del);
}
function deleteSelection(selection) {
var element = document.getElementById("div1");
element.removeChild(document.getElementById(selection));
console.log("deleted");
}
The problem is, when I assign the selection to the buttons ID I have to refer to it by its variable name (actually called 'selection' in the function). When the delete button is pressed I suspect the code looks at the value passed in the onclick function and just sees 'selection' because it has "forgotten" what "selection" was, thus causing an error. Either this or I am not using proper syntax (lack/presence of ' or " quotes) and am thus passing/assigning it incorrectly.
Google Chrome's error console points out this line as the problem:
del.setAttribute("onclick", "deleteSelection(selection)");
specifially citing the 'selection' variable as being not defined in
deleteSelection(selection)
selection is not a global variable - presumably, it's scoped to the function that creates the element. Inline handlers that reference variables can only reference global variables.
But inline handlers are terrible practice anyway, they're basically eval inside HTML markup - better to attach the handler properly with Javascript instead, and no need for any ids:
document.querySelector('#add').onclick = function saveSelection() {
var element = document.getElementById("div1");
var del = document.createElement("button");
del.type = "button";
del.onclick = del.remove;
del.textContent = 'delete';
element.appendChild(del);
};
<div id="add">add</div>
<div id="div1"></div>

Dynamically change the type of a DOM element [duplicate]

Consider the following code:
var element = document.CreateElement("div");
element.toString(); // [object HTMLDivElement]
var element = document.CreateElement("somerandomtag");
element.toString(); // [object HTMLUnknownElement]
My gut instinct is that once an element has been created, it is essentially "strongly typed" (if such a thing exists in JavaScript), because "div" creates a HTMLDivElement and "somerandomtag" creates a HTMLUnknownElement, thus, the tag cannot be changed, because the created object corresponds directly to that tag.
Consider the following code:
var element = document.CreateElement("div");
element.toString(); // [object HTMLDivElement]
element.nodeName = "span"; // Doesn't work.
element.tagName = "span"; // Doesn't work.
So, is it possible to change an element from one type (e.g. "div") to another type (e.g. "span") beyond the object's creation?
EDIT: Please note...MUST be done with pure javascript...NO jQuery or other libraries/apis
An element's tagName is readonly (immutable) no matter what the element is. You cannot change an element's tag name without some rebuilding of the DOM. That is it's not possible to change an existing element, but it's not that difficult to create a new element and append the existing element's children.
var node = document.querySelector('div'),
newNode = document.createElement('span'),
parent = node.parentNode,
children = node.childNodes;
Array.prototype.forEach.call(children, function (elem) {
newNode.appendChild(elem);
});
parent.replaceChild(newNode, node);
http://jsfiddle.net/ExplosionPIlls/wwhKp/

what's the meaning of the functions in javascript?

function ExChgClsName(Obj,NameA,NameB){
var Obj=document.getElementById(Obj)?document.getElementById(Obj):Obj;
Obj.className=Obj.className==NameA?NameB:NameA;
}
<a href="javascript:showMenu(2);">
i am a newbie of the js. so can't understand the above two function very well. expect someone can explain the line's meaning to me one by one. many thanks.
For the first function
var Obj=document.getElementById(Obj)?document.getElementById(Obj):Obj;
The first line gets the object by its ID if Obj is a string that is the ID of a DOM element. Otherwise it leaves the value of Obj alone. This is using the "ternary conditional" operator, a? b: c. which as a value of b if a is truthy and c otherwise. Doing this allows the function to accept a string or a DOM element.
Obj.className=Obj.className==NameA?NameB:NameA;
The next line sets the CSS class of the DOM element from the last line to NameB if the CSS class of the DOM element is NameA and otherwise sets it to NameA. This would have the effect of swapping out the classes so long as another class is never assigned to the element. If another class is assigned to the element, then it will start the cycle again with NameA.
function showMenu(iNo){
ExChgClsName("Menu_"+iNo,"MenuBox","MenuBox2");
}
The second function just applies the first to swap the CSS class of the the DOM element with ID of "Menu_"+iNo between "MenuBox" and "MenuBox2".
Personally, I don't like the first line of the first function because it does two searches of the DOM when it only needs to do one. I would do this
var Obj = document.getElementById(Obj) || Obj;
That should be more efficient on all implementations and is surely more readable. It uses the || operator as a guard to assign Obj back to itself if only if document.getElementById returns null.
Exchange the cascading style sheet class name on an object from A to B
Find the element
if the object's css class name is nameA, set it to nameB, otherwise, set it to nameA
function ExChgClsName(Obj,NameA,NameB){
//ternary operator, sets Obj = the dom object with id = 1st agrument if it exists
//you can get away with this because an object is "truthy" in javascript
// truthy meaning that if you try to evaluate it as a boolean it is the same as true
// if nothing is found getElementById returns null wich is the same as false
var Obj=document.getElementById(Obj)?document.getElementById(Obj):Obj;
//ternary operator again. changes the class of the dom object to the 3rd argument
//if its class is already the 2nd argument
//otherwise it changes it to the second argument
Obj.className=Obj.className==NameA?NameB:NameA;
}
function showMenu(iNo){
//calls exChgCLsName with the specified arguments
ExChgClsName("Menu_"+iNo,"MenuBox","MenuBox2");
}
// Runs the showMenu function when clicked
<a href="javascript:showMenu(2);">

Is it possible to use variables as dom elements?

I have a several input fields in a form each having a unique name. For example, to change the color I would do:
testForm.username.style.background = "yellow";
username being the name of the input and testform being the form name
I want to do this: replace username with a variable elem so that when I call the function to change the background color I don't need to have a separate function for every unique field. I would just send the elem name and that function would work for every field.
testForm.elem.style.background = "yellow";
My problem is it doesn't work. For example it passed the elem into the function fine, but it says that testForm.elem.style is null. For some reason javascript doesn't like variables for element names I'm guessing?
var elem = 'username';
testForm[elem].style.background = 'yellow';
try
testForm [elem].style.background = "yellow";
or
var elem = testForm.username
elem.style.background = "yellow";
in the first case elem holds the username, and in the second case, elem points to the actual DOM element.
A property of a JavaScript object (in this case, the "username" property of the object "testform") can be accessed using either object.property or object["property"] syntax. As the second form takes a string (as shown by the double quotes), it follows that a variable containing a string can also be used with that syntax. Hence:
testform[elem].style.background = "yellow";
will do what you want.
It sounds like you're creating a function to do this anyway. In that case, why not just use the following function:
function changeBackgroundOfElementToYellow(element){
element.style.background = "yellow";
}
And call it with:
changeBackgroundofElementToYellow(testForm.username);
In general I find the RaYell/kangax method posted already to be better, but this is another option.
You'd have to do an eval to do something like that, eg eval("testform." + elem + ".style.background=yellow");

Categories