I'm having some trouble with jQuery in Meteor - I'm just trying to learn so I hope someone could help.
So when #addButton is clicked it will append the div to the .formField and each div created on click will have an unique class, eg formField[1], formField[2] etc
The trouble is when the button is clicked instead of just changing the name of the div only, the div is also added 50 times. I know how dumb it sounds as its a loop, but how would I loop only the div's class on click so each have a different name?
My code is below:
Template.form.events({
'click #addButton': function(event) {
var i;
for (i = 0; i < 50; i++) {
$(".formField").append('<div class="formField['+i+']">.....</div>');
}
return false;
If I understand what you are doing here you don't need a loop. You just need a variable to increment every time the button is clicked. Take your append out of the loop and instead on click increment your variable by one then call an append. No loop necessary.
var i = 0;
Template.form.events({
'click #addButton': function(event) {
i += 1;
$(".formField").append('<div class="formField['+i+']">.....</div>');
}
});
return false;
Do it like this, (i.e. by creating a closure), click run to verify
var uuid = 0;
$('#addButton').on('click', function (event) {
uuid = uuid + 1;
$(".formField").append('<div class="formField[' + uuid + ']">Form' + uuid + '</div>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="formField"></div>
<input type="button" value="Add New" id="addButton"></input>
I'm working on a web app where I need to add a number of input boxes one after the other in order to get commands from the user. I add them using JavaScript to a div with a unique ID to each. The problem I have is once I press enter and the JavaScript function is called to add the next one, the previous input box empties out, and I don't know why.
Here is sample code:
var i = 0;
add_input();
function add_input() {
i++;
document.getElementById('main').innerHTML += "<p>> <input type='text' style='width:90%' id='input" + i + "' onkeypress='press_key(event, this)'></p>";
document.getElementById('input' + i).focus();
}
function press_key(e, t) {
if (e.keyCode == 13) {
add_input();
}
}
<div id='main'></div>
innerHTML will override all existing content and replace them with new ones. You should create a new input element and use insertNode instead.
The addition assignment operator will add the right hand value to the left hand value and then assign the resultant value to the left hand side.
For a quick example:
x += y;
// is equivalent to
x = x + y;
In your code you are basically taking the existing HTML, adding a new chunk of HTML and then assigning that new HTML to the original element replacing the existing HTML. Since the value is not set in the HTML but stored in the DOM it is lost as soon as you assign new HTML to the element (which is when the browser renders it to the DOM replacing the previous DOM).
You could use insertNode as mentioned above or set the HTML attribute to store the value first as the below example shows. However note that this solution is purely to show why the values are disappearing. Doing it this way has an issue that if any of the previous input values are changed only the original value for those inputs would be preserved.
var i = 0;
add_input();
function add_input() {
var curInput = document.getElementById('input' + i);
if (curInput) {
curInput.setAttribute('value', curInput.value);
}
++i;
document.getElementById('main').innerHTML += "<p>> <input type='text' style='width:90%' id='input" + i + "' onkeypress='press_key(event, this)'></p>";
document.getElementById('input' + i).focus();
}
function press_key(e, t) {
if (e.keyCode == 13) {
add_input();
}
}
<div id='main'></div>
innerHTML overwrites all html from the selected element including any user/javascript actions performed on the given html. Thus your input values will be erased with the new html. You are going to want to create an element and then use appendChild. This will maintain the state of your current html elements.
var i = 0;
function add_input()
{
i++;
var input = document.createElement('input');
input.onkeypress=press_key;
input.id = 'input' + i;
document.body.appendChild(input);
input.focus();
}
function press_key(e)
{
//`t` argument is no longer used. Use `this` instead.
if (e.keyCode == 13)
{
add_input();
}
}
<html>
<head>
<script>
</script>
</head>
<body onload='add_input()'>
<div id='main'>
</div>
</body>
</html>
As stated above, your other values disappear due to the inner workings of "innerHTML". In fact, when you do string.innerHTML += string it will replace the HTML for it (meaning what was there before is totally gone and is de-facto replaced with fresh new HTML).
What you want to use is probably appendChild().
With little rewriting I have managed to make your code work:
http://jsfiddle.net/gs1s0fsx/
var i = 0;
function add_input() {
i++;
var main = document.getElementById('main'),
p = document.createElement("p"),
arrow = document.createTextNode('>'),
el = document.createElement('input');
el.type = "text";
el.style = "width:90%";
el.id = "input" + i;
el.addEventListener("keypress", press_key);
main.appendChild(p);
main.appendChild(arrow);
main.appendChild(el);
el.focus();
}
function press_key(e, t) {
if (e.keyCode == 13) {
add_input();
}
}
add
<div id='main'></div>
Hope this helps.
I have the following code
$(document).ready(function () {
$('#big_1').change(function () {
var bigAmt = document.getElementById("big_1").value
+ document.getElementById("big_2").value
+ document.getElementById("big_3").value
+ document.getElementById("big_4").value
+ document.getElementById("big_5").value
+ document.getElementById("big_6").value
+ document.getElementById("big_7").value
+ document.getElementById("big_8").value
+ document.getElementById("big_9").value
+ document.getElementById("big_10").value;
var elem = document.getElementById("totalBig");
elem.value = bigAmt;
});
});
I actually wanted to add the value of big_1 to big_10 on input text value change of "big_1 to big_10" either 1 of the textfield change its value, this should be invoke.
as of now i only run on big_1 change event.
I get an javascript error by adding this way, I think the way I add them up is quite messy.
What should I do to change my code so I can sum up
big_1 to big_10 textfield value, and on change of big_1 to big_10(any of them), it will invoke this and change span id="totalBig" to the value of their sum (big_1 add until big_10)
Below is my edited extra code:
<input type="number" data-bv-digits-message="true" data-bv-threshold="1" min="0" class="form-control" name="big_1" id="big_1" size="6">
<input type="number" data-bv-digits-message="true" data-bv-threshold="1" min="0" class="form-control" name="big_2" id="big_2" size="6">
all the way until big_10
I wanna on change value of any of this big_Identifier(1-10), it will sum it up and change my
<div class="well">
Total Big: <span id="totalbig">0</span> </span>
</div>
I tried the
<script type="text/javascript">
$(document).ready(function() {
$('#html5Form').bootstrapValidator();
$('.big').change(function() {
var bigAmt = "";
$('.big').each(function () {
bigAmt += $(this).val();
})
var elem = document.getElementById("totalBig");
alert(bigAmt);
elem.value = bigAmt;
});
});
</script>
It doesn't run any alert when any of the big_ value was changed.
It would be much better if you added a big class to every single <input id="big_NUMBER">. Then you could do this:
$(document).ready(function() {
$('.big').change(function() {
var bigAmt = 0;
$('.big').each(function () {
bigAmt += Number($(this).val());
})
$("#totalBig").val(bigAmt);
});
});
That's much cleaner and easier to understand than what you had.
In order for this to work, you'll need to add a class to all your inputs:
<input type="number" data-bv-digits-message="true" data-bv-threshold="1" min="0" class="form-control big" name="big_2" id="big_2" size="6"><!-- Notice the big class-->
This is the best way to group all your inputs. They are all related, so they should share a classes. You should not be calling multiple ids for functionality that's so similar.
If you are using jquery, use it properly, it'll make your life a lot easier.
This will work for you in your case exactly
$(document).ready(function() {
$('[id^="big"').change(function(){
var total = (+$('#totalBig').val());
var currentVal = (+$(this).val());
total += currentVal;
$('#totalBig').val(total)
})
});
DEMO
Add class="bigs" to all inputs and then try this:
$(document).ready(function () {
var intTotalBig;
$('.bigs').change(function () {
intTotalBig = 0;
$('.bigs').each(function(){
$thisVal = $(this).val();
if ($.isNumeric($thisVal)){
intTotalBig += parseInt($thisVal, 10);
}
});
$("#totalBig").val(intTotalBig);
});
});
This code check all inputs on every change and sum all of them that has a number value and ignore empty or no number values.
Check JSFiddle Demo
You monitor the change event on all the input type text as follows:
$('input:text').change(
function () {
alert('text changed of any text box.');
//You can doo your code here.
});
Or...
If you want add the monitor to any selected text boxes then you will have to add any css class to those selected text boxes and then monitor those text boxes through class as follows:
$('.yourclass').change(
function () {
alert('text changed of any text box.');
//You can doo your code here.
});
this change event will fire when you lose focus from the text box after changing the text....
but if you want with loosing the focus (means if you want to update the count while typing) then you should use keyup event as stated in this answer.
$(document).ready(function() {
$('#big_1').change(function() {
var divArray = ["big_1","big_2","big_3","big_4","big_5","big_6","big_7","big_8","big_9","big_9","big_10"];
var bigAmt = 0;
for(var i = 0, n = divArray.length;i<n;i++)
{
bigAmt += parseInt($("#" + divArray[i]).val(),10);
}
$("#totalBig").val(bigAmt);
});
});
Try the above, it should do what you're looking for. You'll probably want to use parseInt as well incase the input isn't of "number" type.
*edit, forgot the # for the id.
*edit, removed comment about considering using jquery functions because people are really sensitive.
I am dynamically loading some of the content within my page and would like to get a total of all the data-attributes.
First the elements are cloned and appended
$('.chip').on('click', function () {
$(this).clone().appendTo('.chipPlacement');
});
Then I have written a function that should get the totals
function chipsBet() {
var redchip = $('.chipPlacement .chipValue.r').data() || 0;
var bluechip = $('.chipPlacement .chipValue.b').data() || 0;
var orangechip = $('.chipPlacement .chipValue.o').data() || 0;
var total = redchip.chipValue + bluechip.chipValue + orangechip.chipValue;
return total;
}
Before I append the elements the HTML looks like
<div class="chipPlacement"></div>
and once appended the HTML structure is
<div class="chipPlacement">
<div class="chip red">
<div class="chipValue r" data-chip-value="1">1</div>
</div>
</div>
I need to listen for the DOM structure the change and then fire the chipsBet() function, but I'm not sure how to get this to work. I can't use .on('change') as that only applies to input, textarea and select.
I have tried firing the chipsBet function within the .chip.on('click') but I get NaN returned.
How can I get the data-attribute-values for the new elements in the DOM?
If you don't have a blue or orange chip, you're effectively trying to get .chipValue from 0 which is undefined and adding it to another number gives you NaN.
You can simply iterate over all .chipValue elements within the placement element like so:
function chipsBet()
{
var total = 0;
$('.chipPlacement .chipValue').each(function() {
total += $(this).data('chipValue');
});
return total;
}
Nevermind, you altered your initial question.. carrying on.
<div class='chipPlacement'>
<div class='chip red'>
<div class='chipValue' data-chip-value='1'></div>
</div>
</div>
Then to read your data attributes, you could do something like this.
$('.chip').on('click', function () {
$(this).clone().appendTo('.chipPlacement');
chipsBet();
});
function chipsBet() {
var redchipVal = parseInt($('.chipValue .r').data('chip-value')) || 0;
var bluechipVal = parseInt($('.chipValue .b').data('chip-value')) || 0;
var orangechipVal = parseInt($('.chipValue .o').data('chip-value')) || 0;
var total = redchipVal + bluechipVal + orangechipVal;
return total;
}
I think you want something like bellow. It will call the function every time any change will in div .chipPlacement.
$('.chipPlacement').bind("DOMSubtreeModified",function(){
console.log('Div modified');
});
You can say for your problem
$('.chipPlacement').bind("DOMSubtreeModified",function(){
chipsBet();
});
DEMO
Let's say I have an html form. Each input/select/textarea will have a corresponding <label> with the for attribute set to the id of it's companion. In this case, I know that each input will only have a single label.
Given an input element in javascript — via an onkeyup event, for example — what's the best way to find it's associated label?
If you are using jQuery you can do something like this
$('label[for="foo"]').hide ();
If you aren't using jQuery you'll have to search for the label. Here is a function that takes the element as an argument and returns the associated label
function findLableForControl(el) {
var idVal = el.id;
labels = document.getElementsByTagName('label');
for( var i = 0; i < labels.length; i++ ) {
if (labels[i].htmlFor == idVal)
return labels[i];
}
}
First, scan the page for labels, and assign a reference to the label from the actual form element:
var labels = document.getElementsByTagName('LABEL');
for (var i = 0; i < labels.length; i++) {
if (labels[i].htmlFor != '') {
var elem = document.getElementById(labels[i].htmlFor);
if (elem)
elem.label = labels[i];
}
}
Then, you can simply go:
document.getElementById('MyFormElem').label.innerHTML = 'Look ma this works!';
No need for a lookup array :)
There is a labels property in the HTML5 standard which points to labels which are associated to an input element.
So you could use something like this (support for native labels property but with a fallback for retrieving labels in case the browser doesn't support it)...
var getLabelsForInputElement = function(element) {
var labels = [];
var id = element.id;
if (element.labels) {
return element.labels;
}
id && Array.prototype.push
.apply(labels, document.querySelector("label[for='" + id + "']"));
while (element = element.parentNode) {
if (element.tagName.toLowerCase() == "label") {
labels.push(element);
}
}
return labels;
};
// ES6
var getLabelsForInputElement = (element) => {
let labels;
let id = element.id;
if (element.labels) {
return element.labels;
}
if (id) {
labels = Array.from(document.querySelector(`label[for='${id}']`)));
}
while (element = element.parentNode) {
if (element.tagName.toLowerCase() == "label") {
labels.push(element);
}
}
return labels;
};
Even easier if you're using jQuery...
var getLabelsForInputElement = function(element) {
var labels = $();
var id = element.id;
if (element.labels) {
return element.labels;
}
id && (labels = $("label[for='" + id + "']")));
labels = labels.add($(element).parents("label"));
return labels;
};
document.querySelector("label[for=" + vHtmlInputElement.id + "]");
This answers the question in the simplest and leanest manner.
This uses vanilla javascript and works on all main-stream proper browsers.
I am a bit surprised that nobody seems to know that you're perfectly allowed to do:
<label>Put your stuff here: <input value="Stuff"></label>
Which won't get picked up by any of the suggested answers, but will label the input correctly.
Here's some code that does take this case into account:
$.fn.getLabels = function() {
return this.map(function() {
var labels = $(this).parents('label');
if (this.id) {
labels.add('label[for="' + this.id + '"]');
}
return labels.get();
});
};
Usage:
$('#myfancyinput').getLabels();
Some notes:
The code was written for clarity, not for performance. More performant alternatives may be available.
This code supports getting the labels of multiple items in one go. If that's not what you want, adapt as necessary.
This still doesn't take care of things like aria-labelledby if you were to use that (left as an exercise to the reader).
Using multiple labels is a tricky business when it comes to support in different user agents and assistive technologies, so test well and use at your own risk, etc. etc.
Yes, you could also implement this without using jQuery. :-)
Earlier...
var labels = document.getElementsByTagName("LABEL"),
lookup = {},
i, label;
for (i = 0; i < labels.length; i++) {
label = labels[i];
if (document.getElementById(label.htmlFor)) {
lookup[label.htmlFor] = label;
}
}
Later...
var myLabel = lookup[myInput.id];
Snarky comment: Yes, you can also do it with JQuery. :-)
All the other answers are extremely outdated!!
All you have to do is:
input.labels
HTML5 has been supported by all of the major browsers for many years already. There is absolutely no reason that you should have to make this from scratch on your own or polyfill it! Literally just use input.labels and it solves all of your problems.
with jquery you could do something like
var nameOfLabel = someInput.attr('id');
var label = $("label[for='" + nameOfLabel + "']");
If you're willing to use querySelector (and you can, even down to IE9 and sometimes IE8!), another method becomes viable.
If your form field has an ID, and you use the label's for attribute, this becomes pretty simple in modern JavaScript:
var form = document.querySelector('.sample-form');
var formFields = form.querySelectorAll('.form-field');
[].forEach.call(formFields, function (formField) {
var inputId = formField.id;
var label = form.querySelector('label[for=' + inputId + ']');
console.log(label.textContent);
});
Some have noted about multiple labels; if they all use the same value for the for attribute, just use querySelectorAll instead of querySelector and loop through to get everything you need.
Solution One <label>: One <input>
Using HTML 5.2 reference
Considering the <label> pointing to <input> using for=, the labels element will be a non empty array, and act as a link to the <label> element, accessing all properties of it, including its id=.
function myFunction() {
document.getElementById("p1").innerHTML = "The first label associated with input: <b>" + document.getElementById("input4").labels[0].id + "</b>";
}
<form>
<label id="theLabel" for="input4">my id is "theLabel"</label>
<input name="name1" id="input4" value="my id is input4">
<br>
</form>
<p>Click the "click me" button to see the label properties</p>
<button onclick="myFunction()">click me</button>
<p id="p1"></p>
Solution Many <label>: One <input>
With more than one <label> using for=, you can make a loop to show all of them, like this:
function myFunction2() {
var x = document.getElementById("input7").labels;
let text = "";
for (let i = 0; i < x.length; i++) {
text += x[i].id + "<br>";
}
document.getElementById("p7").innerHTML = text;
}
<b>Three labels for one input</b><br>
<br>
<form>
<label id="theLabel2" for="input7">my id is "theLabel2</label><br>
<label id="theLabel3" for="input7">my id is "theLabel3</label><br>
<label id="theLabel4" for="input7">my id is "theLabel4</label><br>
<input name="name1" id="input7" value="my id is input7">
<br>
</form>
<p>Click the "click me" button to see the label properties</p>
<button onclick="myFunction2()">click me2</button>
<p id="p7"></p>
$("label[for='inputId']").text()
This helped me to get the label of an input element using its ID.
Answer from Gijs was most valuable for me, but unfortunately the extension does not work.
Here's a rewritten extension that works, it may help someone:
jQuery.fn.getLabels = function () {
return this.map(function () {
var parentLabels = $(this).parents('label').get();
var associatedLabels = this.id ? associatedLabels = $("label[for='" + this.id + "']").get() : [];
return parentLabels.concat(associatedLabels);
});
};
A really concise solution using ES6 features like destructuring and implicit returns to turn it into a handy one liner would be:
const getLabels = ({ labels, id }) => labels || document.querySelectorAll(`label[for=${id}]`)
Or to simply get one label, not a NodeList:
const getFirstLabel = ({ labels, id }) => labels && labels[0] || document.querySelector(`label[for=${id}]`)
It is actually far easier to add an id to the label in the form itself, for example:
<label for="firstName" id="firstNameLabel">FirstName:</label>
<input type="text" id="firstName" name="firstName" class="input_Field"
pattern="^[a-zA-Z\s\-]{2,25}$" maxlength="25"
title="Alphabetic, Space, Dash Only, 2-25 Characters Long"
autocomplete="on" required
/>
Then, you can simply use something like this:
if (myvariableforpagelang == 'es') {
// set field label to spanish
document.getElementById("firstNameLabel").innerHTML = "Primer Nombre:";
// set field tooltip (title to spanish
document.getElementById("firstName").title = "Alfabética, espacio, guión Sólo, 2-25 caracteres de longitud";
}
The javascript does have to be in a body onload function to work.
Just a thought, works beautifully for me.
As it has been already mentionned, the (currently) top-rated answer does not take into account the possibility to embed an input inside a label.
Since nobody has posted a JQuery-free answer, here is mine :
var labels = form.getElementsByTagName ('label');
var input_label = {};
for (var i = 0 ; i != labels.length ; i++)
{
var label = labels[i];
var input = label.htmlFor
? document.getElementById(label.htmlFor)
: label.getElementsByTagName('input')[0];
input_label[input.outerHTML] =
(label.innerText || label.textContent); // innerText for IE8-
}
In this example, for the sake of simplicity, the lookup table is directly indexed by the input HTML elements. This is hardly efficient and you can adapt it however you like.
You can use a form as base element, or the whole document if you want to get labels for multiple forms at once.
No checks are made for incorrect HTML (multiple or missing inputs inside labels, missing input with corresponding htmlFor id, etc), but feel free to add them.
You might want to trim the label texts, since trailing spaces are often present when the input is embedded in the label.
The best answer works perfectly fine but in most cases, it is overkill and inefficient to loop through all the label elements.
Here is an efficent function to get the label that goes with the input element:
function getLabelForInput(id)
{
var el = document.getElementById(id);
if (!el)
return null;
var elPrev = el.previousElementSibling;
var elNext = el.nextElementSibling;
while (elPrev || elNext)
{
if (elPrev)
{
if (elPrev.htmlFor === id)
return elPrev;
elPrev = elPrev.previousElementSibling;
}
if (elNext)
{
if (elNext.htmlFor === id)
return elNext;
elNext = elNext.nextElementSibling;
}
}
return null;
}
For me, this one line of code was sufficient:
el = document.getElementById(id).previousElementSibling;
In most cases, the label will be very close or next to the input, which means the loop in the above function only needs to iterate a very small number of times.
Use a JQuery selector:
$("label[for="+inputElement.id+"]")
For future searchers... The following is a jQuery-ified version of FlySwat's accepted answer:
var labels = $("label");
for (var i = 0; i < labels.length; i++) {
var fieldId = labels[i].htmlFor;
if (fieldId != "") {
var elem = $("#" + fieldId);
if (elem.length != 0) {
elem.data("label", $(labels[i]));
}
}
}
Using:
$("#myFormElemId").data("label").css("border","3px solid red");
I know this is old, but I had trouble with some solutions and pieced this together. I have tested this on Windows (Chrome, Firefox and MSIE) and OS X (Chrome and Safari) and believe this is the simplest solution. It works with these three style of attaching a label.
<label><input type="checkbox" class="c123" id="cb1" name="item1">item1</label>
<input type="checkbox" class="c123" id="cb2" name="item2">item2</input>
<input type="checkbox" class="c123" id="cb3" name="item3"><label for="cb3">item3</label>
Using jQuery:
$(".c123").click(function() {
$cb = $(this);
$lb = $(this).parent();
alert( $cb.attr('id') + ' = ' + $lb.text() );
});
My JSFiddle: http://jsfiddle.net/pnosko/6PQCw/
I have made for my own need, can be useful for somebody: JSFIDDLE
$("input").each(function () {
if ($.trim($(this).prev('label').text()) != "") {
console.log("\nprev>children:");
console.log($.trim($(this).prev('label').text()));
} else {
if ($.trim($(this).parent('label').text()) != "") {
console.log("\nparent>children:");
console.log($.trim($(this).parent('label').text()));
} else {
if ($.trim($(this).parent().prev('label').text()) != "") {
console.log("\nparent>prev>children:");
console.log($.trim($(this).parent().prev('label').text()));
} else {
console.log("NOTFOUND! So set your own condition now");
}
}
}
});
I am bit surprised no one is suggesting to use the CSS relationship method?
in a style sheet you can reference a label from the element selector:
<style>
//for input element with class 'YYY'
input.YYY + label {}
</style>
if the checkbox has an id of 'XXX'
then the label would be found through jQuery by:
$('#XXX + label');
You can also apply .find('+ label') to return the label from a jQuery checkbox element, ie useful when looping:
$('input[type=checkbox]').each( function(){
$(this).find('+ label');
});
If you use the for attribute, you can use querySelector(...) to get
the associated label.
HTML/JavaScript
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<label for="myCheckbox">Log Report to Console?</label>
<input name="myCheckbox" type="checkbox" oninput="doSomething(event)" />
<script type="text/javascript">
function doSomething(e) {
const query = `label[for="${e.target.name}"]`; // This is string interpolation NOT JQuery
const label = document.querySelector(query);
}
</script>
</body>
</html>
Plain JavaScript
function doSomething(e) {
// const query = `label[for="${e.target.name}"]`; // This is string interpolation NOT JQuery
// Maybe it is safer to use ".getAttribute"
const query = `label[for="${e.target.getAttribute("name")}"]`;
const label = document.querySelector(query);
// Do what you want with the label here...
debugger; // You're welcome
console.log(label);
}