javascript variable shows in console.log but not in browser output - javascript

I am trying to reuse the output of the year variable.
I will need to reuse the updated value [based on hashchange] in multiple functions later on.
It displays the correct value in the browser console, but it doesn't display in the browser.
<html>
<body>
<p></p>
1
2
</body>
<script>
location.hash = '#2019';
showHash();
var p = document.querySelector('p');
p.innerHTML = window.year;
function showHash() {
return year = location.hash;
}
window.onhashchange = showHash;
</script>
</html>

By assigning location.hash to year you are not modifying p.innerHTML. year and p.innerHTML are not referencing each other's value. When you initialised as follows:
p.innerHTML = window.year;
The value of year was copied so now you have two values which happen to be the same at that moment, but they are not linked so that if you would assign a new value to the one, it would also update the other. No, they are not references.
So in the event handler you should also assign the new hash to p.innerHTML, or better -- as the hash is text -- assign it to p.textContent:
var p = document.querySelector('p');
var year;
function showHash() {
// Assign both to textContent and year (they are independent)
p.textContent = year = location.hash;
// Maybe call some other functions which need to know about `year`
manage();
}
function manage() {
console.log(year);
// ... etc
}
window.onhashchange = showHash;
location.hash = '#2019'; // This triggers showHash, no need to call it explicitly
<p></p>
1
2

Related

How to change h1 text depending on cookie value? [duplicate]

In the following example, why doesn’t the value property of the input with the ID test update to "second"?
document.getElementById("test").addEventListener("click", () => {
let test = document.getElementById("test").value;
test = "second";
console.log(test); // Logs "second", but input value is not updated.
});
<label>Click on this test input: <input type="text" id="test" value="first"></label>
Because Javascript assigned x as a value and not a reference to the original object.
For example, you could instead:
function setText(x) {
document.getElementById('test').value = x;
}
getText = function() {
return document.getElementById('test').value;
}
And the value you set with setText() will be reflected by getText(), since getText() will also use the reference object's value, and not a copy of the value.
EDIT
As Bryan points out, this would be a copy by reference with a global scope:
var test = document.getElementById('test');
function setText(x) {
test.value = x;
}
getText = function() {
return test.value;
}
http://jsfiddle.net/nLj2A/
The original test variable stores a reference to the element, not a value associated with an attribute of the element.
You are copying the value to a variable. Changing the variable won't change the original, because the variable just contains a copy.
If you store the reference of the element in the variable, you can use that to set the value:
var test = document.getElementById('test');
test.value = "second";
You're assigning the element's value to a variable and then changing the variable. This is not reflected back in the element's value. You need to change the element's value instead.
document.getElementById('test').value = "second";
because document.getElementById('test').value
is a getter where as
document.getElementById('test').value = "second"
is a setter
test = document.getElementById('test').value;
...only gives you a copy of the value at that instant. When you modify test, you need to put that back into input field you'd like to change:
var test_input = document.getElementById('test');
test_input.value = "second";
Setting the local variable test to "second" will do nothing. I assume you want getText to update the DOM. Try this:
getText = function() { document.GetElementById('test').value("second"); }
Point to element instead of value: http://jsbin.com/axufi4/edit
Although javascript ultimately treats everything as an object, I believe only arrays and objects are passed by reference. Strings, ints and floats are passed by value.
Text inputs will always give you a string (even if you restrict input to numbers)
<script type="text/javascript">
getText = function() {
var test = document.getElementById('test').value;
test = "second";
//note: if you insert "alert(test)" it returns "second"
document.getElementById('test').value = test;
}
</script>
You need to do this:
document.getElementById('test').value = "second";
or
var el = dcument.getElementById('test');
el.value = "second";
As for why, I believe it has to do with something about Javascript being a "pass by reference" or "pass by value" language, on which subject there was a very interesting discussion here on SO. (I'm not sure on this point, correct me if I'm wrong).
because it's a string and is passed as value, not as reference. so the content of value is copied to test
Because you're setting the value of test to be the string document.getElementById('test').value.
You aren't linking the two together.
If you are looking to do that, you can use a function:
function test(x) {
document.getElementById('test').value = x;
}
test('foo');
In Python, you can do this. In JavaScript, I don't think so.

Javascript's getElementById is not working in my loop

I have an issue with a function I have been working on. The purpose of this function is to take the dates that are inside two sets of text input boxes, calculate the difference between the two, and then place that number of days in a third set of boxes. My function is shown below.
function daysBetween() {
for (var i = 0; i < 8; i++) {
//Get the value of the current form elements
var start = namestart[i];
var end = namend[i];
var out = names[i];
//Duration of a day
var d = 1000*60*60*24;
// Split Date one
var x = start.split("-");
// Split Date two
var y = end.split("-");
/// // Set Date one object
var d1 = new Date(x[0],(x[1]-1),x[2]);
// // Set Date two object
var d2 = new Date(y[0],(y[1]-1),y[2]);
//
// //Calculate difference
diff = Math.ceil((d2.getTime()-d1.getTime())/(d));
//Show difference
document.getElementById(out).value = diff;
}
}
The three arrays referenced by the variables at the beginning contain simply the names of the form elements I wish to access. I've tested the start, end, and out variables with an alert box and the loop runs fine if I do not have the line under the Show Difference comment in the code. I have also gone through and made sure that all names match and they do. Also I have manually run the page eight times (there is eight sets of boxes) with each set of names and it successfully displays 'NaN' in the day box (I have no data in the source boxes as of yet so NaN is the expected behaviour).
When I run the function as shown here what happens is that the first set of text boxes works as intended. Then the loop stops. So my question is quite simple, why does the loop hangup with getElementById even though the names[0] value works, it finds the text box and puts the calculated difference in the box. The text box for names[1] does not work and the loop hangs up.
If you need more detailed code of my text boxes I can provide it but they follow the simple template below.
// namestart[] array
<input type="text" name="start_date_one" id="start_date_one" value=""/> <br />
// namend[] array
<input type="text" name="end_date_one" id="end_date_one" value=""/> <br />
// names[] array
<input type="text" name="day_difference_one" id="day_difference_one" value=""/>
Thanks for any help in advance.
Edit: Noticing the comments I figured I would add my array definitions for refernece. These are defined immediately above the function in my calcdate.js file.
var namestart = new Array ();
namestart[0] = "trav_emer_single_date_go";
namestart[1] = "trav_emer_extend_date_go";
namestart[2] = "allinc_single_date_go";
namestart[3] = "allinc_annual_date_go";
namestart[4] = "cancel_date_go";
namestart[5] = "visitor_supervisa_date_go";
namestart[6] = "visitor_student_date_go";
namestart[7] = "visitor_xpat_date_go";
var namend = new Array ();
namend[0] = "trav_emer_single_date_ba";
namend[1] = "trav_emer_extend_date_ba";
namend[2] = "allinc_single_date_ba";
namend[3] = "allinc_annual_date_ba";
namend[4] = "cancel_date_ba";
namend[5] = "visitor_supervisa_date_ba";
namend[6] = "visitor_student_date_ba";
namend[7] = "visitor_xpat_date_ba";
var names = new Array ();
names[0] = "trav_emer_single_days";
names[1] = "trav_emer_extend_days";
names[2] = "allinc_single_days";
names[3] = "allinc_annual_days";
names[4] = "cancel_days";
names[5] = "visitor_supervisa_days";
names[6] = "visitor_student_days";
names[7] = "visitor_xpat_days";
I reference the file and call my function in my header as such:
<script type="text/javascript" src="calcdate.js"></script>
<script type="text/javascript">
window.onload = daysBetween;
</script>
First and foremost, you can't reference an object by its ID when it doesn't have an ID.
<input type="text" id="start_date_one" name="start_date_one" />
since you say out contains a name you might want to change
document.getElementById(out).value = diff;
to
document.getElementsByName(out)[0].value = diff;
or you could actually just add the id attribute to your html and set it to the same value as the name attribute and you can avoid changing your javascript.
getElementById gets the element by its id attribute, getElementsByName gets all of the elements with the specified name attribute and returns it as an array. In HTML id is supposed to be unique which is why getElementById returns only 1 element

how to put a custom function in a javascript object for use in a html template?

I'm using this pretty handy JavaScript template library: https://github.com/blueimp/JavaScript-Templates.
I can create elements and add data to them as many are doing with underscore.js and mustache.js.
My problem comes when I want to add my own functions and not just strings to the object that will populate the template's various nodes. What i'd like to do is run the function nicetime() to update the time of my newly inserted <div>'s instead of just showing the time once.
Here's the code, and a full demo.
HTML:
<button data-id="1">1</button>
<div data-id="1"></div>
<div id="time_since"></div>
JS:
$(document.body).on('click', 'button', function(){
var id= $(this).data('id');
var data={id:id, string: "just now...", fxn: nicetime()};
var result = tmpl('<div id="string" data-id="'+id+'">{%=o.string%}</div>
<div id="function" data-id="'+id+'">{%=o.fxn%}</div>', data);
$('div[data-id="'+id+'"]').html(result);
nicetime();
});
function nicetime(){
var time = new Date();
var comment_date = setInterval(function() {
var time2 = time_since(time.getTime()/1000);
$('#time_since').html(time2);
return time2;
},
1000);
}
note: inside nicetime() there is a function time_since() which is available on the jsfiddle. It is for formatting the date like this: "1 second ago...".
In javascript functions are objects just like any other variable.
Your problem is that you are invoking the function instead of assigning it to a property.
var data={id:id, string: "just now...", fxn: nicetime()};
instead use only the function name (without the parenthesis)
var data={id:id, string: "just now...", fxn: nicetime};
EDIT
Actually I would take a different approach anyway. Instead of using a timer, just invoke the method as you previously were:
var data={id:id, string: "just now...", fxn: nicetime(this)};
$('div[data-id="'+id+'"]').html(result);
nicetime(this);
I modified nicetime to take the element that tracks the time (i assumed there was a button for each node (otherwise the data would be stored on each node)
function nicetime(el){
var time = $(el).data('start') || new Date();
var time2 = time_since(time.getTime()/1000);
$('#time_since').html(time2);
var comment_date = time2; //still need to figure out where to put this value
$(el).data('start', time)
return comment_date;
}

How to store a div ID value globally

I am creating an application that uses the same number pad to fill out two separate text style form values using javascript.
I found out how to gather a div ID for use inside of a function (for say toggling the hide value), but I need to save this value somehow so that I can know which field to put the numbers into when they come in.
I tried using a global variable for this, but it does not seem to work as the ID does not seem to be recorded as a String value.
The code that I am using does toggle the show/hide attribute, but if I use an alert box to pop what the variable I am using as storage is it reads [object HTMLDivElement]
My script looks like this (bear in mind that I am a noob to javascript).
<script type="text/javascript">
<!--
keypad.display="none";
//Classes for the numberpad on the text fields.
var padName = ""; //Storage for the name of the current pad.
function numPad(field) {
var pad = document.getElementById("keypad"); //manipulating pad.
var ref = document.getElementById(field);//gather the field info.
if (pad.style.display == "block") { //Open or close?
pad.style.display = "none"; //Blank out.
padName = "";
}
else {
pad.style.display = "block";//Set to refer to correct field.
padname = ref;
alert (ref);
}
}
function click(id) {
var key = document.getElementById(id);
var total = padName.value();
if (key == "Backspace") total.slice(0, -1);
else if (key == "Enter") numPad("blanck");
else total += key;
padName.value = total;
}
-->
</script>
// to get the ID by direct property access of the DOM element
var ref = document.getElementById(field).id;
and then ref stores the ID value.
I would suggest:
// create an object to store app-wide settings
// access properties like this: appSettings.propertyName
var appSettings = { padName: "" };
...
var ref = document.getElementById(field).id;
appSettings.padName = ref;
to avoid polluting the global namespace.
To get/set the value of the pad, you'll need to do this:
// to get
var total = document.getElementById(appSettings.padName).value;
// to set
document.getElementById(appSettings.padName).value = "something";
You should read up on DOM objects and properties.
For starters, ref is assigned a reference to a DOM element. You are then assigning this reference to padName, hence the [object HTMLDivElement] alert.
If you just want the ID stored in padName, use
padName = field;
Also, you're mixing cases of padName. You have both padName and padname.
Further, as mentioned in the comments, use the console for debugging. It's much more comprehensive than an alert.
I can't tell what's happening in your click function. You seem to be expecting padName to be an object of some kind however where the value() method and value property comes from is anyone's guess (FYI only form elements have value properties).

If I set `let x = document.getElementById("inputText").value` and update `x`, why doesn’t the value update?

In the following example, why doesn’t the value property of the input with the ID test update to "second"?
document.getElementById("test").addEventListener("click", () => {
let test = document.getElementById("test").value;
test = "second";
console.log(test); // Logs "second", but input value is not updated.
});
<label>Click on this test input: <input type="text" id="test" value="first"></label>
Because Javascript assigned x as a value and not a reference to the original object.
For example, you could instead:
function setText(x) {
document.getElementById('test').value = x;
}
getText = function() {
return document.getElementById('test').value;
}
And the value you set with setText() will be reflected by getText(), since getText() will also use the reference object's value, and not a copy of the value.
EDIT
As Bryan points out, this would be a copy by reference with a global scope:
var test = document.getElementById('test');
function setText(x) {
test.value = x;
}
getText = function() {
return test.value;
}
http://jsfiddle.net/nLj2A/
The original test variable stores a reference to the element, not a value associated with an attribute of the element.
You are copying the value to a variable. Changing the variable won't change the original, because the variable just contains a copy.
If you store the reference of the element in the variable, you can use that to set the value:
var test = document.getElementById('test');
test.value = "second";
You're assigning the element's value to a variable and then changing the variable. This is not reflected back in the element's value. You need to change the element's value instead.
document.getElementById('test').value = "second";
because document.getElementById('test').value
is a getter where as
document.getElementById('test').value = "second"
is a setter
test = document.getElementById('test').value;
...only gives you a copy of the value at that instant. When you modify test, you need to put that back into input field you'd like to change:
var test_input = document.getElementById('test');
test_input.value = "second";
Setting the local variable test to "second" will do nothing. I assume you want getText to update the DOM. Try this:
getText = function() { document.GetElementById('test').value("second"); }
Point to element instead of value: http://jsbin.com/axufi4/edit
Although javascript ultimately treats everything as an object, I believe only arrays and objects are passed by reference. Strings, ints and floats are passed by value.
Text inputs will always give you a string (even if you restrict input to numbers)
<script type="text/javascript">
getText = function() {
var test = document.getElementById('test').value;
test = "second";
//note: if you insert "alert(test)" it returns "second"
document.getElementById('test').value = test;
}
</script>
You need to do this:
document.getElementById('test').value = "second";
or
var el = dcument.getElementById('test');
el.value = "second";
As for why, I believe it has to do with something about Javascript being a "pass by reference" or "pass by value" language, on which subject there was a very interesting discussion here on SO. (I'm not sure on this point, correct me if I'm wrong).
because it's a string and is passed as value, not as reference. so the content of value is copied to test
Because you're setting the value of test to be the string document.getElementById('test').value.
You aren't linking the two together.
If you are looking to do that, you can use a function:
function test(x) {
document.getElementById('test').value = x;
}
test('foo');
In Python, you can do this. In JavaScript, I don't think so.

Categories

Resources