How could i concatenate a variable in the append-function in jquery?
I have a loop where I dynamically creates checkboxes in a html-table. And every checkbox needs a unique id since I attach a listener to each of them after the loop.
What I want is to add the increment variable in the for loop (variable i)
so in every loop the id is concatenated with variable i that is
loop 0, name should be cb0
loop 1, name should be cb1
and so on..
here is what I've tried
$('<td valign="top"></td>').append('<input type="checkbox" id=\"cb\" ' + cnt + '>').appendTo(row);
where cnt is the variable that increments with an integer in each loop
Something is wrong with the concatenation here - greatful for help
Seems you have closed the quote early i.e. it is not adding the cnt variable.
Try
$('<td valign="top"></td>').append('<input type="checkbox" id=\"cb' + cnt + '\">').appendTo(row);
Instead of
$('<td valign="top"></td>').append('<input type="checkbox" id=\"cb\" ' + cnt + '>').appendTo(row);
Have you looked at your output at all?
This code:
'<input type="checkbox" id=\"cb\" ' + cnt + '>'
Would produce this output:
<input type="checkbox" id="cb" 1>
That errant 1 has no relation to the id value. Instead, include it as part of the value. You can also remove the \ characters, since you don't need to escape quotes here:
'<input type="checkbox" id="cb' + cnt + '">'
Which would produce:
<input type="checkbox" id="cb1">
You can use jQuery(html, attributes)
$("<td>", {
valign: "top",
html: "<input type=checkbox id=cb" + cnt + ">"
}).appendTo(row);
Related
I'm learning and trying to put together a little bit of jquery. Admittedly I'm finding it difficult to find a good basics guide, particularly, when adding multiple actions to one page.
I read somewhere that the document listener should only be used once. I believe I'm using it twice here, but not 100% sure how to bring it into one listener.
Also because I've been hacking bits of script together, I think I'm using parts of javascript and parts of jQuery. Is this correct?
A critique of the code below [which does work] and any advice on how best to approach learning jQuery would be most helpful. Thanks.
Script 1 styles a group of 3 radio buttons depending on which one is clicked.
Script 2 appends new inputs to the bottom of a form.
var stateNo = <?php echo $HighestPlayerID; ?> + 1;
$(document).on('click', 'input', function () {
var name = $(this).attr("name");
if ($('input[name="' + name + '"]:eq(1)')[0].checked) {
$('label[name="' + name + '"]:eq(1)').addClass('nostate');
$('label[name="' + name + '"]').removeClass('selected');
}
else {
$('label[name="' + name + '"]').removeClass('nostate selected');
if ($('input[name="' + name + '"]:eq(0)')[0].checked) {
$('label[name="' + name + '"]:eq(0)').addClass('selected');
}
else {
$('label[name="' + name + '"]:eq(2)').addClass('selected');
}
}
});
$(document).on('click', 'button[name=btnbtn]', function () {
var stateName = 'state[' + stateNo + ']';
var newPlayerAppend = `` +
`<tr><td>` +
`<input type="hidden" name="state['` + stateNo + `'][PlayerID]" value="` + stateNo + `" /></td>` +
`<td><input name="` + stateName + `[Name]" value="Name"></td>` +
`<td><input name="` + stateName + `[Team]" type="radio" value="A">` +
`<td><input name="` + stateName + `[Team]" type="radio" value="">` +
`<td><input name="` + stateName + `[Team]" type="radio" value="B">` +
`</td></tr>`;
$("tbody").append(newPlayerAppend);
stateNo++;
});
HTML for the 3 radio button inputs
<td class="Choice">
<label name="state[1][Team]" class="teampick Astate ">A
<input name="state[1][Team]" type="radio" value="A" />
</label>
<label name="state[1][Team]" class="smallx nostate ">X
<input name="state[1][Team]" type="radio" value="" checked />
</label>
<label name="state[1][Team]" class="teampick Bstate">B
<input name="state[1][Team]" type="radio" value="B" />
</label>
</td>
Some of the code can be written more concisely, or more the jQuery way, but first I want to highlight an issue with your current solution:
The following would generate invalid HTML, if it were not that browsers try to solve the inconsistency:
$("tbody").append(newPlayerAppend);
A tbody element cannot have input elements as direct children. If you really want the added content to be part of the table, you need to add a row and a cell, and put the new input elements in there.
Here is the code I would suggest, that does approximately the same as your code:
$(document).on('click', 'input', function () {
$('label[name="' + $(this).attr('name') + '"]')
.removeClass('nostate selected')
.has(':checked')
.addClass(function () {
return $(this).is('.smallx') ? 'nostate' : 'selected';
});
});
$(document).on('click', 'button[name=btnbtn]', function () {
$('tbody').append($('<tr>').append($('<td>').append(
$('<input>').attr({name: `state[${stateNo}][PlayerID]`, value: stateNo, type: 'hidden'}),
$('<input>').attr({name: `state[${stateNo}][Name]`, value: 'Name'}),
$('<input>').attr({name: `state[${stateNo}][Team]`, value: 'A', type: 'radio'})
)));
stateNo++;
});
There is no issue in having two handlers. They deal with different target elements, and even if they would deal with the same elements, it would still not be a real problem: the DOM is designed to deal with multiple event handlers.
There are 2 places you are using anonymous functions. If the code block moves to a named function, the entire code becomes more maintainable. It also helps better in debugging by telling you upfront which function name the error may lie in.
Once you have named functions you will realise that you really do have 2 event listeners for click. So there isn't much benefit of moving them in one listener (or one function you may be referring to). These both event listeners attach on document object and listen to a click event.
Class names are always better when hyphenated. a-state over Astate.
If it works it is correct code, for once you asked about correctness.
It is absolutely fine to have multiple listeners but I usually prefer making everything under one roof. Consider making code as simple as possible which saves lot of time during maintenance.
you can use $(function() {}) or document.ready().
$(document).ready(function() {
$('input[type="radio"]').click(function() {
var thisa = $(this).parent();
var name = $(this).attr("name");
// Remove :selected class from the previous selected labels.
$('label[name="' + name + '"]').removeClass('selected');
// Add conditional class with tenary operator.
thisa.parent().hasClass("smallx") ? thisa.addClass('nostate') : thisa.addClass('selected');
});
$('button[name=btnbtn]').click(function() {
var stateName = 'state[' + stateNo + ']';
// Add TR and TD before appending the row to tbody
var newPlayerAppend = `<tr><td>` +
`<input type="hidden" name="state['` + stateNo + `'][PlayerID]" value="` + stateNo + `" />` +
`<input name="` + stateName + `[Name]" value="Name">` +
`<input name="` + stateName + `[Team]" type="radio" value="A"></td></tr>`;
$("tbody").append(newPlayerAppend);
stateNo++;
});
});
Hope this helps.
I'm creating checkboxes using JQuery as following:
$('<input type="checkbox" ' + 'id=' + (i+1) + '>' + (i+1) + '</input><br/>')
Then later it is removed whenever the user checks the box in:
if (this.checked) {
$(this).remove();
}
However, The input box is deleted, but the number (id) stays on the page, along the <br/> Tag, so I can see the #i there on the HTML Page.
I would like to remove them as well.
So, to in order to make my question as complete as possible, here is how the HTML is laid:
<input id="1" type="checkbox">
1
<br>
Could someone please give me a clue how to remove #i and <br/> from the page?
Thanks
as stated by other answers - input don't have closing tags
You will still need to remove all id and <br />. You can find those with .next() function in jquery. You should put your id in <label> or <span>.
Then. for example:
$(this).next('label').remove();
$(this).next('br').remove();
$(this).remove();
Code can be written shorter but it's for you to see how it works.
The text in <input> text boxes is not set with a textnode (like for textareas), but with the value attribute. (Sorry for the confusion)
Yet, you want to have a checkbox. Best, create a <label> for it, instead of a text node plus a <br /> (which is not handleable with jQuery):
<div class="inputcell">
<input type="checkbox" id="check5">
<label for="check5">5</label>
</div>
With this DOM, you can easily remove the whole box by $("#check5").parent().remove(). Note that single numbers are no valid element ids.
that's because input tags don't have closing tags and remove ignores everything after the >, change this:
$('<input type="checkbox" ' + 'id=' + (i+1) + '>' + (i+1) + '</input><br/>')
to:
$('<input type="checkbox" ' + 'id=' + (i+1) + 'value="' + (i+1) +'"><label>'+ (i+1) +'</label>')
$(this).next('label').andSelf().remove();
input tags don't have closing tag, to create a checkbox you just need the following:
$('<input type="checkbox" ' + 'id=' + (i+1) + '>');
and if you want also to use a label for that checkbox, create appropriate label or any other element, because you can't put closign tag for input and a text between them
This question already has answers here:
unterminated string literal error
(4 answers)
Closed 8 years ago.
I'm trying to use javascript/jquery to dynamically add to a form based on responses to previous elements. However, I keep getting an "unterminated string literal" error. When looking at it with colour-coding/highlighting, it looks fineā¦
Originally I had everything on one line (no escapes), and I got a unterminated string literal error, so I tried escaping new lines, and I got a bad escape error.
Code: http://jsfiddle.net/jshado1/8PTbL/
btw, I looked thru a bunch of older posts, but just found questions from people asking about HEREDOC (which I had looked up previously).
Where is qArray and counter_oneChoice defined?
You'll need to break up the script tags like so:
'<scr' + 'ipt type="text/javascript"> \
$(\'input[name="'+id+'"]\').change(
function(){ counter_oneChoice(qArray, 40);
}); \
</scr' + 'ipt>');'
Otherwise, your jslint errors might just be shortcomings in the linter because of the odd formlation of the code. This is a pretty messed up what to do it.
This is more a remark than an answer but here is a an efficient and readable way to insert big amount of html at once:
make an array
push your markup into the array as strings
join and append
Example:
var id = 0, drug = 'hello', html = [];
html.push('<ul id="' + id + '">');
html.push('<li>In the <span class="highlight">past 12 months</span>, how often did you use <span class="highlight">' + drug + '?</li>');
html.push('<li><input name="' + id + '" type="radio" value="0" />Never</li>');
html.push('<li><input name="' + id + '" type="radio" value="0" />More than once a day</li>');
html.push('<li><input name="' + id + '" type="radio" value="0" />Once a day</li>');
html.push('<li><input name="' + id + '" type="radio" value="0" />More than once a week</li>');
html.push('<li><input name="' + id + '" type="radio" value="0" />Once a week<</li>');
html.push('<li><input name="' + id + '" type="radio" value="0" />More than once a month</li>');
html.push('<li><input name="' + id + '" type="radio" value="0" />Once a month</li>');
html.push('<li><input name="' + id + '" type="radio" value="7" />Less than once a month</li>');
html.push('<li><input name="' + id + '" type="radio" value="77" />I prefer not to answer</li>');
html.push('<li><input name="' + id + '" type="radio" value="99" />Don\'t know</li>');
html.push('</ul>');
$("body").append(html.join(''));
$('input[name="niu12"]').change(function() {
alert("changed");
$('input[name="niu12"][type="radio"]').removeAttr("checked");
var id = this.value;
var drug = $(this).attr("title");
$("#nidu_fq").append('<ul id="'+id+'"> \
<li>In the past 12 months</span>, how often did you use <span class="highlight">'+drug+'</li> </ul>');
}); // done
This works - just keep adding line by line to this.
modified the code a bit. I get errors that some functions are missing.
JS Fiddle Link
I have a simple ui which has a link that says "add item". When this is clicked, a pair of input boxes appears below it. If it is clicked again, yet another pair appears. I'm trying to think of the best way to generate these elements and turn it into some sort of json array of key value pairs (the first input element in each pair being the key and the second input element being the value).
Right now I just have a counter and I generate the ids using it, such as (in the click event of the "add item" link):
$('#features').append('<input id="feature-name-' + self.featureCount + '" type="text" name="asdf" /><a class="delete-feature" data-id="' + self.featureCount + '">Delete</a><input id="feature-description-' + self.featureCount + '" type="text" name="asdf" />');
I don't know what to use as the "name" attributes in order to make it easy to create a json array from them.
you can do something like this without using id attributes.
$('#features').append('<div><input type="text" />
<a class="delete-feature" data-id="' + self.featureCount + '">Delete</a><input type="text" /></div>');
And your javascript,
var yourArray=[];
$('#yourButton').click(function(){
$('#features div').each(function(){
var div=$(this);
var k=$('input:first',div).val();
var v=$('input:first',div).next().val();
yourArray.push({key:k, value: v});
});
});
It doesn't matter what you use for a name attribute, so long as there name and description names are different. Let's say that these elements are all appended to a form with the id myform. Give each pair its own wrapper object. Here, I've used a div, but a fieldset is equally appropriate.
$('#features').append(
'<div class="feature-div">
'<input id="feature-name-' + self.featureCount + '" type="text" name="asdf" />' +
'<a class="delete-feature" data-id="' + self.featureCount + '">Delete</a>' +
'<input id="featurena-description-' + self.featureCount + '" type="text" name="asdf" />' +
'</div>');
Now, it's possible to extract each pair sensibly:
var myarray = [];
$('#myform .feature-div').each(function(i, v) {
myarray.push([
$('input[name=name]', v).val(), $('input[name=description]', v).val()]);
});
Or however you want the data to be presented.
I have a function that is called button and it appends m table using a loop. I have modified the loop so that it assigns an ID to each <td> it makes. However, it does not seem to be working right.
Here it is in action, follow the use case below to test it: http://jsfiddle.net/JEAkX/19/
Here is a simple use case I use to test it:
Change the letter in a cell
Press "More"
Change the letter in one of the new cells
It should function the same as the original cells if the ID was getting assigned properly.
The counter is: var n = 13;
and it is inserted into the appended cell as such:
cell.innerHTML = "<input type='text' id='r"+ (n) +"' size='1' onChange='getPos('r"+ (n++) +"'), modifyCells('alphabetTable')' value='" + subset[i++] + "' />"`
This is the DOM source I am getting:
<td><input id="r13" size="1" onchange="getPos(" r14="" ),="" modifycells(="" alphabettable="" )="" value="q" type="text"></td>
<td><input id="r14" size="1" onchange="getPos(" r15="" ),="" modifycells(="" alphabettable="" )="" value="r" type="text"></td>
I suspect it has to do with cramming everything into 1 line like #zzzzBov said but I dont know how else to do it.
Besides the n++, there's a quoting issue in your HTML. There are nested single quotes in the onchange attribute, like so:
<input type='text' id='r19' size='1' onChange='getPos('r20'), modifyCells('alphabetTable')' value='p' />
Quick fix for the syntax is to use escaped double quotes, so you can get going:
cell.innerHTML = "<input type='text' id='r"+ n +"' size='1' onChange='getPos(\"r"+ (n++) +"\"), modifyCells(\"alphabetTable\")' value='" + subset[i++] + "' />"
Separation of HTML/CSS/JS notwithstanding.... You need 3 levels of quotes. Also, the comma in the onclick event needs to be a semicolon.
Perhaps:
cell.innerHTML = "<input type='text' id='r" + n + "' size='1'
onChange='getPos(\"r" + (n++) + "\"); modifyCells(\"alphabetTable\")'
value='" + subset[i++] + "' />"