Binding an input element to a JavaScript object - javascript

I want to introduce a simple notation to bind a HTML <input> element to a JavaScript object. Something like:
<script>
var qform = {
uid : "",
pass : ""
};
</script>
<form method="get" action="#">
<input id="temp0" type="text" name="uid" bind="qform.uid" />
<input id="temp1" type="password" name="pass" bind="qform.pass" />
<input type="submit" value="submit" />
</form>
So that any changes to the <input>s will change my JS variable. The way I'm trying to implement it is:
<script>
var x = 0;
for(x = 0; x < 2; x++) {
var inputField = document.getElementById("temp" + x);
var bindObj = inputField.getAttribute("bind");
var bindObjTree = bindObj.split(".");
var parent = window;
for (var i = 0; i < bindObjTree.length - 1; i++) {
parent = parent[bindObjTree[i]];
}
child = bindObjTree[bindObjTree.length - 1];
inputField.value = parent[child];
inputField.onchange = function() {
var xp = parent;
var xc = child;
xp[xc] = inputField.value;
alert(JSON.stringify(window["qform"]));
};
} // for
</script>
However only the second input field behaves the way I want to. Can someone explain why that is? I'm guessing it has something to do with closures. I'm really trying to understand what I'm doing wrong rather than find a solution (I can easily work around this with JQuery, but I don't really want that).

The issue is with these:
parent = parent[bindObjTree[i]];
child = bindObjTree[bindObjTree.length - 1];
and
inputField.onchange = function() {
var xp = parent; // Always refers to the element retrieved at index 1 of the for loop
var xc = child; // Always refers to the element retrieved at index 1 of the for loop
// This is regardless of which input's event handler executes
xp[xc] = inputField.value;
alert(JSON.stringify(window["qform"]));
};
These will always refer to the elements found in the last iteration of the for loop because of closure.

inputFields needs to be an an array so it doesn't get overwritten in the loop or
you can place an id in the form tag and instead reference it to get the fields as its child elements.

Your child variable is global. Try to use:
var child = bindObjTree[bindObjTree.length - 1];
instead. Since it is global, you will overwrite the global child variable on the second turn.

Related

Passing variables through addEventListener

I am trying to add event to all inputs, get the value (number) from those and insertHtml them into span elements.
This is my javascript code. I have no idea how to pass the variables.
var input_selector = document.querySelectorAll('.coins_n'); // input number elements
var price_selector = document.querySelectorAll('.price'); // span elements
for(var i = 0; i <= input_selector.length; i++) {
var input = input_selector[i];
var price = price_selector[i];
input.addEventListener('input', function(){
console.log(price); // not working
console.log(input); // not working
price.innerHTML = input.value; // not working
})
}
The problem here has to do with scoping of your variables. var is a weird one, whose scope isn't really limited to the block, but to the containing function. The following two are (essentially) the same:
var input;
var i = 0;
for(; i < input_selector.length; i++) input = input_selector[i];
and
for(var i = 0; i < input_selector.length; i++) var input = input_selector[i];
both create a variable named input in global scope, and then update that variable. That means that any functions that wants to read input later will just read the last version of input, and not the version at the time you defined the handler you would trigger later.
let, however, is block scoped, and your for loop is a block. So defining let input inside the for loop will mean that input is defined uniquely for every iteration of the loop, since every time the block gets executed a new scope is created for everything in there.
The same is true for var i = 0 in your for loop - any handler that calls it later will just log the last global value of i, but if you use let, that's not the case and every iteration of the loop has its own i. So your code could simply be reduced to this:
const input_selector = document.querySelectorAll('.coins_n');
const price_selector = document.querySelectorAll('.price');
for( let i = 0; i < input_selector.length; i++ ){
input_selector[i].addEventListener('input', event => {
price_selector[i].innerHTML = event.target.value;
});
}
This is pretty complex to explain once you start typing it out, so better read what other have already written at something like MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
Ok. I've managed it by using let.
var input_selector = document.querySelectorAll('.coins_n');
var price_selector = document.querySelectorAll('.price');
for(var i = 0; i < input_selector.length; i++) {
let input = input_selector[i];
let price = price_selector[i];
input_selector[i].addEventListener('input', function(){
price.innerHTML = this.value;
})
}

How can I get my input value from input field in a div using JavaScript

I am trying to get the value from an input field and display it using a div tag, but it's not displaying anything. Where am I wrong?
var num = document.getElementById("inputNum").value;
var numbersList = document.getElementById('numbers').innerHTML = num;
<input type="text" id="inputNum">
<div id="numbers">
</div>
Here is the code,
HTML
<input type="text" id="inputNum">
<div id = "numbers">
</div>
Javascript
var num = document.getElementById("inputNum");
var numbersList = document.getElementById('numbers');
num.onkeyup= function(e){
numbersList.innerHTML = e.target.value;
}
keyup will detect every key that is being typed and it will display to the div
Use a onkeyup event. This will give you ever character from text box. After getting the value you can easily set it using innerHTML. Consider the following snippet:
<script>
function setValue(){
var num = document.getElementById("inputNum").value;
document.getElementById('numbers').innerHTML = num;
}
</script>
<input type = "text" id ="inputNum" onkeyup="setValue()">
<div id = "numbers">
In var numbersList = document.getElementById('numbers').innerHTML = num; just omit var numbersList =. Code document.getElementById('numbers').innerHTML = num; will set innerHTML of Element with Id = "numbers" and will not return anything.
Your code will be:
var num = document.getElementById("inputNum").value;
document.getElementById('numbers').innerHTML = num;
or just
document.getElementById('numbers').innerHTML = document.getElementById("inputNum").value;
You have a few problems, and your needs aren't totally clear, but hopefully this will help. Here are the things I fixed:
This line
var numbersList = document.getElementById('numbers').innerHTML = num;
contains an error because it has two equals signs. I replaced it with two lines, first identifying the element and saving it to the variable numbersList, then setting the innerHTML property of numbersList to the num discovered above.
Secondly, the javascript you've written will presumably run once, when the page is loaded. At that time the input contains no text, so there's nothing to copy to the div. Depending on what you're trying to do, there are a few ways to handle this, but as one example, I've put the code you wrote (with the above fix) into a function, then added a button and assigned the function to run when the button is clicked.
Please let me know if you have any questions.
function copyVal() {
var num = document.getElementById("inputNum").value;
var numbersList = document.getElementById('numbers')
numbersList.innerHTML = num;
}
document.getElementById('copy').onclick = copyVal;
<input type = "text" id ="inputNum">
<div id = "numbers"></div>
<button id="copy">copy text</button>
So a few things is happening below.
First, we ensure that the whole page is loaded. Why? If your script is loaded at the beginning, it may have troubles accessing the DOMs (input, textarea, div, etc). Of course, if you load the Javascript at the botton of your page, you can skip such issue.
However, I decided to implement the (function() {...}); self-execute function. This will ensure your Javascript runs after the page its loaded.
Then, I added an event listener to the DOM object of inputNum. This listener will keep an eye to keyup events of your keyword. Each time a key goes up, after being pressed, it will run the code inside the function.
// This function will execute when the whole page is loaded
// This means that all the DOMs (such as your input and div) will be available
(function() {
var inputNum = document.getElementById("inputNum");
inputNum.addEventListener("keyup", function(){
var num = inputNum.value;
document.getElementById('numbers').innerHTML = num;
});
})();
<input type = "text" id ="inputNum">
<div id = "numbers"></div>
Note: I could have use the attribute keyup='' in the input field; however, I decided to give you an answer that provides 100% control. In this way, you can decide which type of event is more appropriate to the project you are working with.
var num = document.getElementById("inputNum");
var numbersList = document.getElementById('numbers');
num.addEventListener('change', function(){
numbersList.textContent = this.value;
})
Try this:
var num = document.getElementById("inputNum").value;
document.getElementById('numbers').innerHTML = num;

Making variables assigned HTML ids with a function

I can make variables one by one like this:
var bookName = document.getElementById('bookName').value,
author = document.getElementById('author').value,
translator = document.getElementById('translator').value,
pageCount = document.getElementById('pageCount').value,
publisher = document.getElementById('publisher').value,
isbn = document.getElementById('isbn').value,
printingYear = document.getElementById('printingYear').value;
But it's so hard to write and it doesn't fit with the DRY rule. So I changed the code to this:
function variableMaker(argument) {
var tags = document.getElementsByTagName(argument);
for (var i = 0; i < tags.length; i++) {
var tags[i].name = tags[i].value;
}
}
variableMaker(input);
But I can't understand if it is the true way or if it is working? How do I check if it's true or not?
In this code, I tried to get the computer find all the input tags and make variables with their name property and assign it to its values for each of them.
If I understand correctly then you want to gather data from all <input> elements. If so, then you need to call it like this:
variableMaker('input'); // use quotes!
Still even then your function does not return anything, it just ends.
You'd also better create your own object for the return collection, instead of adding values to an existing object.
Here is a working solution:
function variableMaker(tagName) {
var elements = document.getElementsByTagName(tagName);
var items = {};
for (var i = 0; i < elements.length; i++) {
var elem = elements[i];
items[elem.id] = elem.value; // Use id as key, each points to the corresponding value.
}
return items;
}
var values = variableMaker('input');
console.log(values); // show the entire return object
console.log(values.author); // access individual items from the return object
console.log(values.isbn);
<input type="text" id="author" value="Dahl">
<input type="text" id="isbn" value="1234">
.

Accessing an element using id (JavaScript)

Scenario: I have a form element with id = "shipping_address"
Will all of the following work:
var i = document.shipping_address;
var i = window.shipping_address;
var i = shipping_address;
var i = document.forms.shipping_address;
var i = windows.forms.shipping_address;
var i = forms.shipping_address:
Thank you in advance!
Here is a running example:
var i = document.shipping_address;
console.log(i);
var i = window.shipping_address;
console.log(i);
var i = shipping_address;
console.log(i);
var i = document.forms.shipping_address;
console.log(i);
var i = windows.forms.shipping_address;
console.log(i);
var i = forms.shipping_address;
console.log(i);
<form id="shipping_address">
<input type='text'/>
</form>
Also I created a JSFiddle to help you.
https://jsfiddle.net/hszknwn9/1/
please notice you have what I think is a typo in the last line:var i =
forms.shipping_address:
the : should be a ;
I corrrected it in jsFiddle
You can try all of them on Codepen.io, but I would use only:
var i = document.getElementById("shipping_address");
And then access all the properties listed here according to what you need.
Those will not work.
If you are trying to assign the reference of your element with id="shipping_address", the correct way would be:
var i = document.getElementById("shipping_address");
To access the individual fields (and their respective contents) of that element, you need to first access the array of elements in your <form> element, and then iterate through:
var fields = i.elements;
var responses = [];
for(var j = 0; j < fields.length; j++) {
//perform actions on or with fields[j],
// such as responses.push(fields[j].value);
// which would put the value of each field
// of the form into the responses array.
}
The <form> element is a special container for grouping individual <input> elements, each of which should specify its input type. For example,
<form id="shipping_address">
<input type="text" placeholder="Street Address/P.O. box"></input>
<input type="text" placeholder="Town/City Name"></input>
<input type="text" placeholder="State/Country Name"></input>
<input type="text" placeholder="Zip Code (if applicable)"></input>
</form>
Which would create 4 input simple text fields from which inputs could be gathered. Putting all of this together, we can create a function that returns an array containing all of the values of the input fields in your shipping_address form element:
function getAddress() {
var i = document.getElementById("shipping_address");
var fields = i.elements;
var responses = [];
for(var j = 0; j < fields.length; j++) {
responses.push(fields[j].value);
return responses;
}
And from there on you can handle that data however you wish.
There are many more input types, I suggest you read the reference documentation at the w3schools html form reference, which provides acceptable documentation for most of the elements.
Hope this helps!
Use this to get value of a element by referencing ID of the element:
document.getElementById('shipping_address').value;

Use array value as variable name

I need to use jQuery's keyup function to take the value from input html form elements and display said values in a div elsewhere.
The working code looks as follows:
$('#name').keyup(function() {
var name = $(this).val();
$('#name-in-document').html(name);
});
Since I have many identical instances of the above code block, I'd like to use a for loop to loop through an array of values. The catch is the name of the variable in the second line
var name = $(this).val();
would come from the array.
I have tried the following loop, which does not work because (as I understand it) a Javascript variable cannot be named an array value:
var inputsArray = ["phone", "name", "address"];
for (var i = 0; i < inputsArray.length; i++) {
$("#"+inputsArray[i]).keyup(function() {
var inputsArray[i] = $(this).val();
$("#"+inputsArray[i]+"-in-document").html(inputsArray[i]);
})
};
So I have two questions:
Is it true that I cannot use the array values to create a variable in the for loop?
Is there an alternate way to accomplish the same thing (getting the variable names from the array) that might work?
I am just beginning JavaScript and really appreciate any insight. Thank you!
1. It is not true
2. You'll need to make a closure over the variable i or over the value from inputArray[i] and inside the event-bind the keyword this refers to the DOMNode witch triggers the event:
Read more absout closures here How do JavaScript closures work?
var inputsArray = ["phone", "name", "address"],
i = 0,
len = inputsArray.length;
for ( ; i < len; i ++ ) {
makeKeyupBind(inputsArray[i]);
}
function makeKeyupBind( value ) {
$("#" + value).on("keyup", function() {
$("#" + value + "-in-document").html( this.value );
});
}
That variable only exists within the scope of the function passed as a callback for the keyup event so I don't really see the need to give it a dynamic name; you could call it absolutely anything at all and not run into conflicts.
For the alternative approach, I would recommend giving #name (and his friends) a class name, e.g.
<input class="js-key-up" id="name" />
Then you can do away with the array and the for loop altogether. Also, adding new HTML elements would not require adding items to the array.
HTML
<input class="js-key-up" id="phone">
<input class="js-key-up" id="name">
<input class="js-key-up" id="address">
<p id="phone-in-document"></p>
<p id="name-in-document"></p>
<p id="address-in-document"></p>
JavaScript
​
$('.js-key-up').keyup(function (e) {
var id = $(this).attr('id');
$('#' + id + '-in-document').html($(this).val());
});​
I've created a jsfiddle with the code in.
Try this:
var inputsArray = ["phone", "name", "address"];
for (var i = 0; i < inputsArray.length; i++) {
$("#"+inputsArray[i]).keyup(function() {
var valuesArray[i] = $(this).val();
$("#"+inputsArray[i]+"-in-document").html(valuesArray[i]);
})
var inputsArray = ["phone", "name", "address"];
for (var i = 0; i < inputsArray.length; i++) {
$("#"+inputsArray[i]).keyup(function() {
var htmlValue = $(this).val();
$("#"+inputsArray[i]+"-in-document").html(htmlValue);
})
I think you don't need to name variable from array, do you?
You can build a selector straight from the array and skip the loop completely. Use the id of the current input to create the selector for the other element
var inputsArray = ["phone", "name", "address"];
$('#'+ inputsArray.join(',#') ).keyup(){
$('#'+this.id+"-in-document").html( $(this).val() );
})
This will create the selector:
$('#phone,#name,#address')
Above assumes that you are trying to find elements :
$("#phone-in-document").html(val);
$("#name-in-document").html(val);/* etc*/
#Wes Cossick: this line inside of the loop is wrong:
var valuesArray[i] = $(this).val();
if you want to do it that way declare the array before the loop. that is problem of OP
#diana: if i understand you correct, you want to add a dynamic keyup handler to every item in the array? if it is that way, that code should do it (dont reassign items in the array!) the trick is to create a closure (code is untested).
var inputsArray = ["phone", "name", "address"];
for (var i = 0; i < inputsArray.length; i++) {
(function(item) {
$("#"+item).keyup(function() {
$("#"+item+"-in-document").html($(this).val());
});
})(inputsArray[i]);
};
if you are using jQuery (and it seems so ;-), take a look at the each-function in jQuery: http://api.jquery.com/jQuery.each/
that should be a lot easier for you ;-)

Categories

Resources