Understanding Getting and Setting nodeValue - javascript

I am updating a text value and I'm not sure why the first block of code doesn't work, but the alternate block does. Can someone explain this to me? They seem equivalent.
//doesn't update
newAtomicNum = 2;
oldAtomicNum = document.getElementById("atomicNumber").firstChild.nodeValue;
oldAtomicNum = newAtomicNum;
*versus* //does update
newAtomicNum = 2;
oldAtomicNum = document.getElementById("atomicNumber");
oldAtomicNum.firstChild.nodeValue = newAtomicNum;

When calling nodeValue without setting it, it returns the current nodeValue, not a reference to the property.
So an element looking like
<div id="atomicNumber">test</div>
Where you call
var oldAtomicNum = document.getElementById("atomicNumber").firstChild.nodeValue;
oldAtomicNum now contains the string test, so setting the variable to something else does not update the elements nodeValue

They're very different indeed.
In your first example, all you're updating is the variable, oldAtomicNum. There's no enduring link between that and document.getElementById("atomicNumber").firstChild.nodeValue at all. Assignment (=) copies values, it doesn't create references.
Note that this is very different from this:
newAtomicNum = 2;
atomicNum = document.getElementById("atomicNumber").firstChild;
atomicNum.nodeValue = newAtomicNum;
...which updates the value. The reason that works is that on the second line, the value we're copying into atomicNum is an object reference. Then we use that reference on the third line, assigning to one of the object's properties.

Related

html + js: dataset variable being ovewriten after assigning it a value based on src attribute

So I have a for loop that iterates over a list of iframes:
var iFr;
for (var i = 0; i < iFrames.length; i++) {
iFr = iFrames[i];
if (isFooBar()) {
iFr.dataset['sourceBackup'] = iFr.src; //assign src value to data-source-backup
iFr.removeAttribute('src'); // remove src attribute
}
}
The weird part is that it seems to remove the src value also from dataset['sourceBackup'] or data-source-backup which I don't understand why. As I'm doing it AFTER assigning it to dataset['sourceBackup'].
UPDATE:
I even tried using object.assign() :
iFr.dataset['sourceBackup'] = Object.assign({}, {'src': iFr.src}).src;
Yet still the iFr.dataset['sourceBackup'] dataset gets erased for some iframes elements but not for others which is confusing.
Update 2
The problem was with outer code not with the code here. I was having multiple references to the same iframe in different contexts. So this was causing the weird behavior.
This is happening because both iFr.dataset['sourceBackup'] and iFr.src are pointing to the same object. The assignment does NOT make a copy of the object. Therefore, when you remove the object, it is not available regardless of which reference you use.
To actually clone the object, see this answer: How do I correctly clone a JavaScript object?

Setting Variable Assignments with property display

I'm still a novice when it comes to JavaScript and was trying to make my code more cleaner and was wondering why the top scenario works but the bottom doesn't? Am I missing something?
var partner = document.getElementById('partner');
var providedBy = document.getElementById('providedBy');
partner.style.display = "none";
providedBy.style.display = "none";
But this does not?
var partner = document.getElementById('partner');
var providedBy = document.getElementById('providedBy');
collection = partner + providedBy;
collection.style.display = "none";
In the console it gives me error saying Cannot set Property 'display' of undefined. Am I supposed to define it somewhere first? I console logged the new variable and it returned both div elements.
collection is of type string as the + operator automatically call for both their toString() function.
Now what you are trying is to access a property of collection.style which does not exist because you are operating on a string. That's the reason for the error message you are getting.
You could do something like:
var collection = [];
collection.push(document.getElementById('partner'));
collection.push(document.getElementById('providedBy'));
collection.forEach(function(element) {
element.style.display = 'none';
}
which would be something I think you are trying to archive.
just to complement the accepted answer, I think you should understand why you get this error.
For what i understand from your code, you are trying to set the css of both variables partner and providedBy to display : none.
Your first piece of code works because you do this separately, while in your second code you try to add with the (+) operator both nodes, which evaluates to the string "[object HTMLDivElement][object HTMLInputElement]".
Then you try to call .style on that string which evaluates to undefined, and then you try to call display on that undefined value, this is where you get the error.
You could leave your code just like that since there are not too many variables, but if you wanted to do something that worked on multiple variables you could
create an array
push your objects into the array
create a function that loops over the elements of the array and set their style.display = "none" to individually.
In JavaScript you have to declare all of your variables. Secondly, you can't point to two objects at once by using the + operator. JavaScript interprets this as trying to concatenate the two objects, which it can't do in this way. It will return the string [object Object][object Object]
In order to affect two Objects at the same time you would need to create a function or use an existing method.

javascript ternary operator inside variable

okay im working with a friend and he sent me js file which included a variable that included the ternary operator. I cant figure out how to change it to if..else. can you help please?
also i noticed ".length" didnt have the normal "()" after it, is there a reason why?
var nextRadioTab = activeRadioTab.next().length ? activeRadioTab.next() : $('#contentslider div:eq(0)');
Does this work?
if (activeRadioTab.next().length) {
var nextRadioTab = activeRadioTab.next();
} else {
var nextRadioTab = $('#contentslider div:eq(0)');
}
In JavaScript, objects are more-or-less just a list of names pointing to values. Each name-value pair is called a "property".
These values themselves can be any type of value, including a function. If the value of a property is a function, we call that a "method".
Say you want an object to track the x and y coordinates of a point.
var point = { x: 10, y: 20 };
In this case we can just use simple values, because we don't need any behaviour more advanced than getting a value (alert(point.x)) or setting one (point.x = 10).
jQuery is designed to let your code work on different browsers; different browsers behave differently in lots of situations, so jQuery can't just let you set
element.text = "hello world"
because depending on the type of object element is, it will need to modify different properties on different browsers. For this reason, jQuery makes you use methods for things like this:
element.text("hello world")
The .length attribute of a jQuery object is simple; it's controlled by jQuery itself and doesn't need to do any special things in different browsers. For this reason, you just use it directly. If they needed more complicated behaviour, they would use a function/method instead:
var myObject = { length: 2 }; // myObject.length
var myObject = { length: function() { return 2; } }; // myObject.length()
var nextRadioTab;
if (activeRadioTab.next().length)
nextRadioTab = activeRadioTab.next();
else
nextRadioTab = $('#contentslider div:eq(0)');
length is a property of whatever next() returns, which is most likely the same type of object as activeRadioTab.

How do I optimize this Javascript?

I tried to convert snippet 1 to snippet 2 but this did not work (the text fields did not clear). f3aa and f3bb are each text fields that I need to clear after a sumbit.
Snippet 1
var target=document.getElementById('f3aa');
target.value='';
var target=document.getElementById('f3bb');
target.value='';
Snippet 2
o1('f3aa')=o1('f3bb')='';
Snippet 3
function o1(a)
{
document.getElementById(a);
}
Assuming I've understood your question correctly, you were nearly there:
document.getElementById('f3aa').value = '';
document.getElementById('f3bb').value = '';
In your snippet 2, you are trying to assign an empty string to a DOM element, rather than the value property of that element.
In snippet 1, you assign a DOM element to the target variable, and then assign an empty string to the value property of the target variable. As target contains a DOM element, you assign that string to the value property of that element, which is equivalent to the code I have shown above.
You forgot to include the attribute names from your first snippet in your second:
document.getElementById('f3aa').value='';
document.getElementById('f3bb').value='';
(Note that this isn't really an "optimization" - there will be no noticeable difference in how quickly the two snippets run. Use whichever is more readable.)
X('f3aa').value = X('f3bb').value = '';
where X is your query-by-ID implementation.
Live demo: http://jsfiddle.net/zmr29/
(I wrote a X function in my demo, but I assume that you either use a library or have some other shorthand for DOM queries.)
I think it's illegal to use var to declare a variable more than once in the same scope.
This code is bad:
var test = true;
var test = false;
This code is good:
var test = true;
test = false; // <-- no "var" keyword here

Dynamic Javascript - Is This Valid?

can someone tell me if this is valid javascript? I know you couldnt do this sort of thing in c# but js is a much looser language..
var arrayToUse = "arr" + sender.value;
for (i = 0; i <= arrayToUse.length; i++) {
// something..
}
specifically - the dynamic generation of the array name..
update..
so i have an array called arrMyArray which is initialised on document ready. sender.value = "MyArray" - but could be something else eg MyArray2
I want to dyanimcally iterate over the array that is indicated by the sender.value value.
Yes, this is entirely valid.
arrayToUse will be a string (regardless of the value of sender.value — it will be converted to a string), and i will iterate from 0 to the string's length).
One minor note: it should be for (**var** i = 0; …), otherwise i will be treated as a global variable, which will almost certainly end badly if you've got multiple loops running at the same time.
Edit: you want to get the array based on the name? In that case you've got to look it up in whatever context the array is defined.
If it's a global array, use window.
For example:
var arrayName = "arr" + sender.value;
var array = window[arrayName];
…
To get a variable name defined by a variable, you need to use eval, like so:
var arrayToUse = eval("arr" + sender.value);
However, you must be very careful with this, because controlling sender.value would allow someone to hijack your entire application this way. You should usually try to find another solution.
If the variable is defined at the globally, you can look it up as window["arr" + sender.value] instead. This is still not ideal, but is less of a security risk.
What you need to do is access a variable with the name "arr" + sender.value. Accessing the variable whose contents are "arr + sender.value doesn't do what you want -- that's just a string.
To access the variable with that name, you can look it up as a global (globals are members of the window object in the browser):
window["arr" + sender.value]
This is safer and faster than using eval() because it doesn't run code in a JavaScript execution context to evaluate the string -- it just looks up a variable in the window object with that name.

Categories