Variable within quote within quote? - javascript

Im trying to use inner html and dynamically set an onclick statement that contains a variable:
cell5.innerHTML="<input type='button' value='Remove' onclick='removerow('manual_" + (num) + "')' />"
So lets say the num variable was set to 4. The output should be onclick="removerow('manual_4')"
Any help?

The best thing would be to avoid all this:
var input = document.createElement('input');
input.type = 'button';
input.value = 'Remove';
input.onclick = function() {
removerow('manual_' + num);
};
cell5.appendChild(input);
Depending on the relationship between the button, the cell and the row to be removed, you could also do DOM traversal inside the handler to get a reference to the row.

You can escaped nested quotes using \:
"...onclick=\"removerow('manual_" + (num) + "')\"..."

cell5.innerHTML='<input type="button" value="Remove" onclick="removerow(\'manual_' + (num) + '\')" />'

You can escape the quotes using \
So
onclick=\"removerow('manual_" + (num) + "')\"

Consider using a click event instead. It makes that sort of thing clearer:
$(".cell5") // whatever selector you want
.html('<input type="button" value="Remove"/>')
.click(function(){
removerow('manual_' + row);
});
Also consider using the row number as the input instead of a string. If they all have the same form you can simplify things with just:
removerow(row);
Clearly that is an API design decision, but it would simplify this expression if it makes sense.

Related

addeventlistener to indexed element

I have a list of elements. However, the length of this list varies between trials. For example, sometimes there are 6 elements and sometimes there are 8. The exact number is detailed in an external metadata.
To display this variable list, I've written:
var html = '';
html += '<div id="button' + ind + '" class="buttons">';
html += '<p>' + name + '</p></div>';
display_element.innerHTML = html;
If I were to 'inspect' the elements in my browser, they would appear to have IDs of button0.buttons, button1.buttons, etc.
Now I am trying to attach event listeners to each element but my code is not working so far. Different forms of broken code below:
document.getElementById("button' + ind + '").addEventListener("click", foo);
$("#button' + ind + '").click(foo);
document.getElementById("button").addEventListener("click", foo);
$("#button").click(foo);
Any help would be very appreciated! Thanks.
You wrong at concat string update it as
document.getElementById("button" + ind).addEventListener("click", foo);
var html = '';
var ind = 1;
var display_element = document.getElementById("test");
html += '<div id="button' + ind + '" class="buttons">';
html += '<p>' + name + '</p></div>';
display_element.innerHTML = html;
document.getElementById("button" + ind).addEventListener("click", foo);
function foo(){
alert('click');
}
<div id="test"></div>
Use "document.getElementsByClassName" get all botton elements then foreach to add click function.
document.getElementsByClassName('buttons').map( element => { element.addEventListener("click", foo) })
To answer the question of why neither of those uses of document.getElementById() are working for you, you are mixing your quotes incorrectly. "button' + ind '" evaluates to exactly that, rather than evaluating to "button0", "button1", etc. To make your code more readable, and to avoid similar quote mixing issues, I would recommend looking into template literals https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
With modern JS if you want to execute the same function you won't require to add an id to each button.
Just use the class added to the buttons like this:
document.querySelectorAll('.buttons').forEach(button => {
button.addEventListener('click',foo);
});
Then use the event parameter in that function to get the target node & execute whatever you want. You can also add data attributes in those buttons to use while executing that function.

Variable in the middle of a string

$('#attachments').append("<tr><td><b>Attachment " + next + "</b><input id='upload" + next + "'name='files'" + "onchange='showUpload('" + next + "') type='file' value='System.Collections.Generic.List`1[System.Web.HttpPostedFileBase]'></td></tr>");
The above code is printing the following in the browser. What am I doing wrong?
<input id="upload1" name="files" onchange="showUpload(" 1') type="file" value="System.Collections.Generic.List`1[System.Web.HttpPostedFileBase]" class="valid" aria-invalid="false">
onchange="showUpload(" 1') needs to be onchange="showUpload('1')
I recommend using string interpolation (template literals) instead. To find out if your browser supports template literals, check Can I Use.
It's far easier to get this right. I've added newlines so it's readable. Making your HTML on one line like that is just impossible to read:
var content = `<tr><td>
<b>Attachment ${next}</b>
<input id="upload${next}"
name="files"
onchange="showUpload('${next}')"
type="file"
value="snipped for brevity">
</td></tr>`;
$('#attachments').append(content);
What this does is fairly intuitive: the template literal, delineated by backticks, will replace each instance of ${next} with the value in the next variable.
I have also taken the liberty to change all of your attributes to use double quotes for consistency. Hopefully I didn't make any typos.
Superficially "onchange='showUpload('" closes the onchange value before the function's parameter, which leads to malformed HTML.
What am I doing wrong?
What you're really doing wrong is that you're adding inline event handlers with jQuery, which leads to problems exactly like that.
var tr = $("<tr><td><b>Attachment " + next + "</b></td></tr>").appendTo("#attachments");
$('<input>', {
id: "upload" + next,
name: "files",
type: "file",
value: "System.Collections.Generic.List`1[System.Web.HttpPostedFileBase]"
}).on( 'change', function() { showUpload(next); } )
.appendTo(tr.find('td'));
You can simply escape a character
$('#attachments')
.append("<tr><td><b>Attachment " + next + "</b><input id='upload" + next + "' name='files' onchange='showUpload(\"" + next + "\")' type='file' value='System.Collections.Generic.List`1[System.Web.HttpPostedFileBase]'></td></tr>");

Dynamically create an element with an event handler that takes a string

This is driving me insane.
I create a cell in a table dynamically through:
tr.append("<td>" + countryArr[i].ISO_id + "</td>");
I created a button that when clicked calls a function with the value countryArr[i].ISO_id. This value is a string and needs to be called in "quotes".
I cannot get the function to be called with quotes.
I've tried:
tr.append("<td><button type='button' onclick='showCyclists(" + cId + ")'>Show country's cyclists</button></td>");
tr.append("<td><button type='button' onclick='showCyclists("" + cId + "")'>Show country's cyclists</button></td>");
tr.append("<td><button type='button' onclick='showCyclists('" + cId + "')'>Show country's cyclists</button></td>");
None of these work. Please help
With ES6 you you could just use the following called template literals, note the backticks `
tr.append(`<td><button type='button' onclick='showCyclists("${cId}")'>Show country's cyclists</button></td>`);
Just add escaped quotes showCyclists(\"" + cId + "\"):
tr.append("<td><button type='button' onclick='showCyclists(\"" + cId + "\")'>Show country's cyclists</button></td>");
You can't use single quotes because those are being used to delineate the attribute. You could use escaped double quotes to get this to work:
tr.append("<td><button type='button' onclick='showCyclists(\"" +
cId +
"\")'>Show country's cyclists</button></td>");
However, while it is possible to get your approach to work by manipulating the strings, the solution you are trying to use here (inline event handlers, and furthermore, inline event handlers created from JavaScript strings) is a bad practice.
Save yourself some headaches and build up the elements properly. Your code might be a few lines longer, but it will be cleaner.
Good approach:
var button = $('<button type="button">')
.text("Show country's cyclists")
.on('click', function () { showCyclists(cId) });
var td = $('<td>').append(button);
tr.append(td);
Working example:
function showCyclists(id) {
console.log("Here are all the cyclists.");
console.log(id);
}
var tr = $('tr');
var cId = '12345';
var button = $('<button type="button">')
.text("Show country's cyclists")
.on('click', function() { showCyclists(cId); });
var td = $('<td>').append(button);
tr.append(td);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr></tr>
</table>

Having difficulty building a form summary with JS

Sorry for the noobish question but, I am trying to build a form summary that will populate a div (immediately) with all of the fields being used. Here is a small sample of the field: Fiddle
For some reason the JS is not working as I would expect it to, can anyone point out what I am doing wrong?
For example, I would like it to output: "AND name: john EXCEPT number 222".
I would also like to be able click on a result to remove it, and clear the field. Thank you
$(".allS").change(function () {
if ($(this).next('.textArea').not(':empty'))
// varible to hold string
var str = "";
$("select option:selected").each(function () {
str += $(this).text() + " ";
});
$("#text_here").text(str);
}).change();
$('.textArea').change(function(){
var $inputs = $('form#form :input[type="text"]'),
result = "";
$inputs.each(function(){
// access the individual input as jQuery object via $(this)
result += $(this).val()+"<br>";
});
// store result in some div
$('div#text_here').text(result);
}).change();
There were many mistakes in your code. I simplified it to a very short code that only does what's needed to get the output you requested. Here's the working fiddle.
$(".allS, .textArea").change(function () {
var str = '';
if ($('#name').val().length > 0 && $('#number').val().length > 0)
var str = $('#nameMod>option:selected').text() + ' name:' + $('#name').val() + ' ' + $('#numberMod>option:selected').text() + ' number ' + $('#number').val();
$("#text_here").html(str);
});
Basically, what this does is attach a change event handler to both classes (.alls, .textArea), and when the event is triggered, both input fields are tested for any content. If this test passes, a string is composed out of all the relevant values, and the div content is set. If the test failed (no content), the str variable contains an empty string and the div is cleared.
Just glancing at the code, the selector 'form#form :input[type="text"]' looks wrong. For starters, input is not a pseudoclass. Also, attribute matching shouldn't have the quotes.
This may or may not be what you want (I think it is, from looking at your html):
'form#form input[type=text]'
Also your <br>'s are not working because you called text(). call html() instead.

jQuery: trying hook a function to the onclick when page loads

I have seen a similar question, HERE and have tried that, but I can't seem to get it working.
Here is my code for dynamically generating table rows.
for (var contribution = 0; contribution < candidate.contributions.length - 1; contribution++) {
var id = candidate.contributions[contribution].donor_id;
var uid = candidate.contributions[contribution].user_id;
$("#history-table").append(
"<tr onclick='" + parent.viewEngine.pageChange('public-profile', 1, id, uid) + ";>" +
"<td class='img-cell'>" +
"<img class='profile-avatar-small' src='/uploads/profile-pictures/" +
candidate.contributions[contribution].image + "' alt='' /></td><td class=''>" +
"<h2>" + candidate.contributions[contribution].firstname +
" " + candidate.contributions[contribution].lastname + "</h2></a><br/><br/>" +
"<span class='contribution-description'>" + candidate.contributions[contribution].contribution_description + "</span></td>" +
"<td><h3>$" + formatCurrency(candidate.contributions[contribution].contribution_amount) + "</h3></td></tr>");
}
This still executes the click event as soon as the page loads, which is not the desired behavior. I need to be able to click the tr to execute the click event.
Pass the whole thing as a string:
"<tr onclick='parent.viewEngine.pageChange(\'public-profile\', 1, " + id + ", " + uid + ");>" // + (...)
But, as you are using jQuery, you should be attaching the click handler with .on().
(I really don't recommend using inline event handlers like that, especially when you're already using jQuery, but anyway...)
The problem is that you need the name of the function to end up in the string that you are passing to .append(), but you are simply calling the function and appending the result. Try this:
...
"<tr onclick='parent.viewEngine.pageChange(\"public-profile\", 1, " + id + "," + uid + ");'>" +
...
This creates a string that includes the name of the function and the first couple of parameters, but then adds the values of the id and uid variables from the current loop iteration such that the full string includes the appropriately formatted function name and parameters.
Note that the quotation marks around "public-profile" were single quotes but that wouldn't work because you've also used single quotes for your onclick='...', so you should use double-quotes but they need to be escaped because the entire string is in double-quotes.
I'm wondering if you might be better simplifying things a bit.
If your rows are being dynamically added, then try putting some kind of meta-data in the <tr> tag, e.g. something like this:
<tr id="id" name="uid">
Then try the following with your jQuery (v.1.7 required):
$('#history-table tr').on('click', function(){
parent.viewEngine.pageChange('public-profile', 1, this.id, this.name);
});
This will likely require modification depending on how your page rendering works but it's a lot cleaner and easier to read having been removed from your main table markup.
Well that's because you're executing the function, not concatenating it. Try:
onclick='parent.viewEngine.pageChange("public-profile", 1, id, uid);'
Take this ->
$("#contribution-" + uid).click(function(){
parent.viewEngine.pageChange('public-profile',1, id, uid);
});
And do two things:
1) Move it outside of the 'for' statement
As soon as the for statement is executed, the click function will be executed as well. The click function is not being supplied as a callback function in this for statement.
2) Change it to ->
$("tr[id^='contribution-'").on('click', function(){
var idString = $(this).attr("id").split("-"); //split the ID string on every hyphen
var uid = idString[1]; //our UID sits on the otherside of the hyphen, so we use [1] to selec it
//our UID will now be what we need. we also apply our click function to every anchor element that has an id beginning with 'contribution-'. should do the trick.
parent.viewEngine.pageChange('public-profile',1, id, uid);
});
This is my solution.

Categories

Resources