I am currently learning JavaScript, and I got stuck at the following problems: I have tried to dynamically create an input of type text from JavaScript and to set its onChange method, but it is fired only when the page is loaded. In addition, document.onload does not work for creating my input, but window.onload does, although the tutorials I read claim that these two are almost the same thing. The code is the following:
<html>
<head>
<script type="text/javascript">
function f(value) {
alert(value);
return true;
}
window.onload = function() {
if (document.getElementById("cloned") == null) {
var clonedInput = document.createElement('input');
clonedInput.type = 'text';
clonedInput.value = "";
clonedInput.id = 'cloned';
clonedInput.size = 20;
clonedInput.onChange = f(clonedInput.value);
var lastChild = document.getElementById("parent");
document.body.insertBefore(clonedInput, lastChild);
}
};
</script>
</head>
<body>
<input id="toClone" type="text"/>
<div id="parent"></div>
</body>
</html>
f(clonedInput.value) calls the function immediately and sets its return value (which is true in this case) as event handler.
You want to use an anonymous function:
clonedInput.onchange = function(){ f(this.value); };
Note: While HTML attributes are case-insensitive, JavaScript object properties are not.
You can actually clone the existing input element:
if (document.getElementById("cloned") == null) {
var clonedInput = document.getElementById("toClone").cloneNode(true);
clonedInput.id = 'cloned';
clonedInput.onchange = f;
var lastChild = document.getElementById("parent");
document.body.insertBefore(clonedInput, lastChild);
}
Now to read the value change f to this:
function f() {
var value = this.value;
alert(value);
return true;
}
Edit: to make the cloned input reflect the first "live" you'll have to attach couple of events:
if (document.getElementById("cloned") == null) {
var orgInput = document.getElementById("toClone");
var clonedInput = orgInput.cloneNode(true);
clonedInput.id = 'cloned';
clonedInput.onchange = f;
orgInput.onkeypress = ReflectValue;
orgInput.onchange = ReflectValue;
var lastChild = document.getElementById("parent");
document.body.insertBefore(clonedInput, lastChild);
}
Then have this function:
function ReflectValue() {
var cloned = document.getElementById("cloned");
cloned.value = this.value;
}
Now whenever user type in the first input, it will reflect in the second input, and whenever user focus out it will also reflect any "non-keyboard" changes like pasting text.
Related
I'm having this little bump in a function, normally if the variable "receivedRDB" is undefined in the DOM, it is dynamically created in a form and if it is defined it takes the value of another variable "receivedR". But "receivedRDB" keeps being created, even when it is already defined in the DOM.
var receivedRDB = document.getElementsByName('receivedR')[0];
if (typeof receivedRDB !== "undefined") {
receivedR = JSON.parse(receivedRDB.value.split(",").slice(0));
} else {
receivedR = [];
}
if (typeof receivedRDB !== "undefined") { //never detected
receivedR.push(toRemoveR);
receivedRDB.value = JSON.stringify(receivedR).replace(/"\[\\|\\"]|\\"/g, "");
} else { //problematic part
event.preventDefault();
receivedR.push(toRemoveR);
var input = document.createElement("input");
input.type = "hidden";
input.name = "receivedR";
input.value = JSON.stringify(receivedR);
rForm.appendChild(input);
}
Here's a solution based on the fact that getElementsByName is a "live" list
Anywhere in your code you can put
var receivedRDB = document.getElementsByName('receivedR');
then change your code to
if (receivedRDB.length !== 0) {
receivedR.push(toRemoveR);
receivedRDB[0].value = JSON.stringify(receivedR).replace(/"\[\\|\\"]|\\"/g, "");
} else {
event.preventDefault();
receivedR.push(toRemoveR);
var input = document.createElement("input");
input.type = "hidden";
input.name = "receivedR";
input.value = JSON.stringify(receivedR);
rForm.appendChild(input);
}
I guess <script> tag which uses receivedRDB appears earlier than the DOM (in <head> for example). If so, there is more than one way to solve.
<script defer>
add an attribute defer to the <script> tag will make the JavaScript code be run after DOM is loaded
window.onload = function(){ /* ... */ }
window.onload will be called after DOM is loaded.
window.addEventListener('load', function(){ /* ... */ })
More compatible one (more than one function can be called individually)
If not the problem please include the minimal code to reproduce the problem.
I amm develloping an web form with multiple text box with same css class.
and i want to bind a specific method to all these textboxes who use that class.
belows are my codes
window.onload = function ()
{
var tObj = document.getElementsByClassName('exa');
for (var i = 0; i < tObj.length; i++) {
tObj[i].onblur(convertAmount(event,this));
}
}
the another function 'convertAmount()' is below
function convertAmount(evt, obj) {
if (obj.value != "") {
var num = parseFloat(obj.value);
num = Math.round((num + 0.00001) * 100) / 100;
obj.value = num.toFixed(2);
}
else {
obj.value = "0.00";
}
}
html codes
<div>
<input type="text" id="finalvalue" class="exa"/>
<input type="text" id="grossvalue" class="exa"/>
<div>
when browser load first time only '0.00' values are coming on those text boxes. but when i type some values on those text boxes and press tab its not working! please help what is wrong here
As commented before, you should assign a eventHandler and not pass it as callback.
So you code would be:
tObj[i].onblur = convertAmount.bind(this, event, this);
Also, event is default argument for any eventListener and current object/element is automatically binded to it, so above code can be simplified to
tObj[i].onblur = convertAmount;
This will bind the context and you will get all properties in this.
Sample Fiddle
Note: you should use addEventListener instead. onBlur = will replace all previous events. addEventListener will add another one.
Sample Fiddle
I hope this link helpful to you.
<div>
<input type="text" id="finalvalue" class="exa"/>
<input type="text" id="grossvalue" class="exa"/>
<div>
$(document).ready(function(){
$('.exa').each(function(index,value){
$(this).attr('onblur',convertAmount(event,$(this)))
})
})
function convertAmount(evt, obj) {
if (obj != "") {
$(obj).val('0.00')
}
else {
$(obj).val('0.00')
}
}
I have 3 text boxes in my mvc4 asp.net View.
Code is:-
<table>
<tr><td>A:</td><td>#Html.TextBox("A")</td></tr>
<tr><td>B:</td><td>#Html.TextBox("B")</td></tr>
<tr><td>Answer:</td><td>#Html.TextBox("C")</td></tr>
</table>
For Example,What i want is,
As soon as i enter "3" in TextBox A and "2" in TextBox B, the answer "5" should be displayed instantly in TextBox C, without me hitting any submit button.
How can i do this?
Thank You.
Here another solution using JQuery
SAMPLE DEMO
For using JQuery you need to add JQuery lib in your head tag , just copy paste the below line in head tag.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
JQuery:
<script type="text/javascript" >
$(document).ready(function (){
$("#Txt_1").on('input', function () {
sumCal();
});
$("#Txt_2").on('input', function () {
sumCal();
});
function sumCal() {
var txt1 = $("#Txt_1").val();
var txt2 = $("#Txt_2").val();
var result = Number(txt1) + Number(txt2);
$("#Txt_3").val(result);
}
});
</script>
You need to use some form of Javascript to do this. Here is a piece of vanilla JavaScript which adds an event handler onto both A and B, which compares the value of the textboxes and displays the required value in C if the condition is met:
// Get all the textboxes by their IDs
var textboxA = document.getElementById("A");
var textboxB = document.getElementById("B");
var textboxC = document.getElementById("C");
// Add a handler for the keyup event
textboxA.addEventListener("keyup", showAnswer, false);
textboxB.addEventListener("keyup", showAnswer, false);
function showAnswer() {
// Convert the values from a string to a float
var valA = parseFloat(textboxA.value);
var valB = parseFloat(textboxB.value);
// Make sure both values are valid numbers
if(!isNaN(valA) && !isNaN(valB)) {
// Show the calculated value in the C box
textboxC.value = valA + valB;
}
else {
// Can't do any calculations, just show a blank value
textboxC.value = "";
}
}
Here is a fiddle to demonstrate.
There are easier ways of doing this with jQuery:
$(function() {
$("#A, #B").on("keyup blur", function() {
var valA = parseFloat($("#A").val());
var valB = parseFloat($("#B").val());
if(!isNaN(valA) && !isNan(valB)) {
$("#C").val(valA + valB);
}
else {
$("#C").val("");
}
});
});
Try this
$(document).ready(function(){
$("#txtbox2").keyup(function(){
var txt01= parseInt ($("#txtbox1").val(),10);
var txt02= parseInt( $("#txtbox2").val(),10);
$("#txtbox3").val( txt01+txt02);
});
});
I have put together this piece of JavaScript, but I am struggling with the code as I'm a newbie. What I want to do is when a button is clicked it will change the background color opacity. The code below does this, but now I want the button to be reverted to the normal state when I click it again.
How can I do this? Thanks..
Normal state: background="rgba(255,0,0,0.8)"; Pressed state:
background="rgba(255,0,0,0.6)";
function highlight(id) {
document.getElementById(id).style.background="rgba(255,0,0,0.6)";
}
I would use a CSS class:
.opacityClicked{
background:rgba(255,0,0,0.8);
}
.opacityDefault{
background:rgba(255,0,0,0.6);
}
And change your function to:
function highlight(id) {
var element = document.getElementById(id);
element.class = (element.class == "opacityClicked") ? "opacityDefault" : "opacityClicked";
}
Or if you want to use only JavaScript
var isClicked = false;
function highlight(id) {
isClicked = !isClicked;
var element = document.getElementById(id);
element.style.background = (isClicked == true) ? "rgba(255,0,0,0.6)" : "rgba(255,0,0,0.8)";
}
Update(See comments: if you use 2 buttons):
var buttonClicked = null;
function highlight(id) {
if(buttonClicked != null)
{
buttonClicked.style.background = "rgba(255,0,0,0.8)";
}
buttonClicked = document.getElementById(id);
buttonClicked.style.background = "rgba(255,0,0,0.6)";
}
You could do something really quick like this:
First, add a hidden input element to your page like so:
<input type="button" id="foobar" value="FooBar!" onclick="highlight('foobar')" style="background-color:rgba(255,0,0,0.8);" />
<input type="hidden" id="one_neg_one" value="1" /> <= hidden element
Next, put this in your highlight function:
function highlight(id) {
var a = 7;
var o = document.getElementById("one_neg_one");
var newa = (a + (parseInt(o.value) * -1)) * 0.1;
document.getElementById(id).style.background="rgba(255,0,0," + newa + ")";
o.value = o.value * -1;
}
That should work, although I agree with a previous answer that you should use a css class for this.
#Ruben-J answer works fine. There is a syntax error though - you should instead use element.className rather than element.class.
https://developer.mozilla.org/en-US/docs/Web/API/Element/className
Below is an updated answer using the correct syntax:
function highlight(id) {
var element = document.getElementById(id);
element.className = (element.className == "opacityClicked") ? "opacityDefault" : "opacityClicked";
}
Also noticed that this answer doesn't show the HTML. Make sure to pass through the id element, not the name of the id.
I have the following Javascript that on a single mouse click in a table cell with id="freq-table" populates consecutive <input> form fields with id="searchTerm(x)" with the cell's value. It's referenced in the <body> tag as:
<body onload="populateFields()>
and <table> tag as:
<table onclick="populateFields()>
var index=0;
function populateFields(){
var ft_id = document.getElementById("freq-table");
var alltds = ft_id.getElementsByTagName("td");
for (var i in alltds) {
alltds[i].onclick = function () {
if(index==0) {
searchTerm1.value = this.innerHTML;
} else {
setThis(this.innerHTML);
}
}
}
if (index<2) {
index++;
} else {
index = 1;
}
}
function setThis(value) {
document.getElementById("searchTerm"+index).value = value;
}
When trying to make the function more universal by passing the element id (as follows), it now takes a SECOND mouse click to start populating the fields.
<table onclick="populateFields(this)" id="freq-table">
function populateFields(element){
var alltds = element.getElementsByTagName("td");
What is it about the revision that's changing the behavior? Am I just incorrectly passing the id? Or is revised function now expecting a variable to be passed to it in <body> tag? It's confusing because: If I am incorrectly passing the id, why would the function work consecutively AFTER the first mouse click? What is the fix for this, please?
You have some heavy code here, where the first table click (or body onload) sets additional click event handlers.
What you should do instead is use event delegation. With event delegation, the click event handler is attached to the table but knows which cell was clicked (the target).
[Update] Code sample based on the above article:
var index=0;
var tableIds=["freq-table1","freq-table2","freq-table3"];
for (var i=0;i<tableIds.length;i++) {
var currentId=tableIds[i];
var table=document.getElementById(currentId);
table.onclick = function(event) {
event = event || window.event;
var target = event.target || event.srcElement;
while(target != this) {
if (target.nodeName == 'TD') {
// target is our cell
setThis(target.innerHTML);
}
target = target.parentNode;
}
// increment index modulo 3
index=(index+1)%3;
}; // end of onclick function
} // end of for loop
Live demo: http://jsfiddle.net/srVmF/2/
I think the call can come from the TD or the TR element. So, the first time the id will be 'undefined'.
Why not call the function with the event and verify the tag name:
<table onclick="populateFields(event)" id="freq-table">
Javascript
function populateFields(e) {
var source = e.target || e.srcElement;
if (e.tagName == 'table') {
var ft_id = document.getElementById(source.id);
Instead of being populated on page load, now you have to click on the table before it populates the fields.
You could leave the page load handler:
<body onload="populateAllFields()">
For every table you add a class:
<table class="mytable">
Then, the code:
function populateAllFields()
{
[].forEach.call(document.getElementsByClassName('mytable'), populateFields);
}
Your <body onload="populateFields()> isn't passing the element you want, so the initial set that would be done when the page loads is no longer happening.
You can fix it by passing the ID instead, and give the onload handler the ID.
function populateFields(id){
var ft_id = document.getElementById(id);
var alltds = ft_id.getElementsByTagName("td");
// and so on...
}
<body onload="populateFields('freq-table')">
<table onclick="populateFields(this.id)">