Anonymous function in dynamically generated list producing SyntaxError - javascript

I want to place an onclick event inside a dynamically generated list. I can't use it as it is, like updateRoomID(arg), because it would fire immediately. So I placed it inside an anonymous function, as advised by various sources online: function (){updateRoomID(arg)}. But this results in: "Uncaught SyntaxError: Unexpected token (". Developer tools says the problem is at function().
The section of code it's in:
socket.onmessage = function(event) {
var msg = JSON.parse(event.data);
for (let i = 0; i < msg.length; i++) {
if (msg[i].beingserved == false) {
listRooms.innerHTML += '<li id=' + msg[i].roomid +
// Problem on following line.
' onclick=' + function () { updateRoomID(msg[i].roomid) } +
'>' +
'<a href="#">' +
msg[i].roomid +
'</a></li>';
} else {
document.getElementById(msg[i].roomid).remove();
};
};
};
I've tried it with the function as a string inside quotations marks: <li id=' + msg[i].roomid +' onclick="function(){updateRoomID(msg[i].roomid)}">'. I've tried placing the onclick handler in href link instead, and also replaced it with addEventListener. But I got the same error with these attempts.
If I try function(){updateRoomID(arg)}() with the parentheses behind, it fires immediately as expected.
I've been looking through it all day and can't figure out where the syntax error is. I'm quite unfamiliar with JavaScript. What am I doing wrong?

You can't put a function in the onclick attribute. It contains JavaScript source code that should be executed.
What you should do in this case is put the function call as a string, but substitute in the value of the argument.
Using a template literal makes this easier.
listRooms.innerHTML += `
<li id="${msg[i].roomid}" onclick="updateRoomId(${msg[i].roomid})">
${msg[i].roomid}
</li>`;

Related

How to pass variable into a onclick function

I am wanting to try and pass record.ItemID to my onclick = buy() function. But I am getting errors like "Uncaught SyntaxError: Unexpected end of input"
I have tried \"record.ItemID \" but that of course just passes the literal string of result.name
I have also tried (\'' + record.ItemID + '\') but get the same Syntax error
function showShop(items) {
let tableContent = "<tr class='orderTitle'><td =imgTable></td><td id = contentTable ></td></tr>\n";
let odd = true;
const addRecord = (record) => {
tableContent += odd ? "<tr class='orderOdd'>" : "<tr class='orderEven'>";
odd = !odd;
tableContent += "<td>" + "<img id = image src="+ "http://redsox.uoa.auckland.ac.nz/ms/MuseumService.svc/shopimg?id=" + record.ItemId + " />" + "</td><td id = content>" + record.Description + "<td><button onclick='buy("+ record.ItemId +")'/> Buy </button></td>";
}
items.forEach(addRecord)
document.getElementById("shop").innerHTML = tableContent;
}
function buy(item){
window.open('http://redsox.uoa.auckland.ac.nz/mss/Service.svc/buy?id='+ item,'_self');
}
I'm not sure if this will solve your problem but it looks like you're mixing up 's and "s.
onclick='buy('record.ItemId')'
You are terminating the onclick attribute right after buy(.
You may need to do something like:
onclick='buy(" + record.ItemId + ")'
Generally speaking though, if you have to build up HTML in strings, you are better off string interpolation. It makes it easier to read and is less prone to these types of issues.
Example:
const html = `<button onclick="buy(${record.ItemId})">Click</button>`;
It looks like you're trying to build up some HTML content to put into a table, and you want some behaviour attached to a button inside the table so that it opens a new window when you click on it.
There are a number of different approaches to what you're trying to do which would be safer in production code, so while you've got some answers to your specific question, please consider these alternative approaches which are more idiomatic:
You could use a link (<a>) instead of a button, and use CSS to make the link look like a button. This avoids needing a click handler at all.
You could use data attributes to store the record in a safe way, then access it from the click event, e.g. e.target.dataset.recordId.
You could use jQuery or a similar toolkit to create the button, then attach a function to the button as a click handler.
When you create HTML directly like you are doing in your question, you're opening your code up to code injection, where someone malicious could craft data that could steal private information from users of your site. It's much safer to use a library to construct your HTML directly rather than building it up in strings.
Really you're much better off separating out your inline JS and using event listeners to target classes on your elements.
Here's a quick example to show you how you might achieve that:
const records = [{ itemId: 1 }, { itemId: 2 }, { itemId: 3 }];
const imgRoot = 'https://dummyimage.com/30x30/676767/fff.png?id=';
// `map` iterates over the array and produces one element of HTML per record
// We use a class on the button to identify it, and a data attribute
// button to hold the itemId
const html = records.map(({ itemId }) => {
return `
<div class="itemWrapper">
<img class="item" src="${imgRoot}${itemId}" />
<button data-itemid="${itemId}" class="buyRecord">Buy record</button>
</div>
`;
});
document.querySelector('.root').innerHTML = html.join('');
// We grab the buttons and iterate over them attaching
// event listeners that call `handleBuy` when the button is clicked
const buyButtons = document.querySelectorAll('.buyRecord');
buyButtons.forEach(button => button.addEventListener('click', handleBuy, false));
function handleBuy(e) {
// Destructure the itemid from the dataset of the button
// click event
const { target: { dataset: { itemid } } } = e;
console.log(itemid);
}
<div class="root" />
Documentation
map
Data attributes
Template literals
Destructuring assignment
The General format of onclick is
onclick="function_name(variable)"
For this case you can do something like this:
tableContent += '<td>' + '<img id = image src="http://redsox.uoa.auckland.ac.nz/ms/MuseumService.svc/shopimg?id=' + record.ItemId + '" /></td><td id="content">' + record.Description + '<td><button onclick="buy('+record.ItemId+')"> Buy </button></td>';

Passing argument to on click event of dynamically generated element

I am trying to pass arguments to onclick event of dynamically generated element. I have already seen the existing stackoveflow questions but it didn't answer my specific need.In this existing question , they are trying to access data using $(this).text(); but I can't use this in my example.
Click event doesn't work on dynamically generated elements
In below code snippet, I am trying to pass program and macroVal to onclick event but it doesn't work.
onClickTest = function(text, type) {
if(text != ""){
// The HTML that will be returned
var program = this.buffer.program;
var out = "<span class=\"";
out += type + " consolas-text";
if (type === "macro" && program) {
var macroVal = text.substring(1, text.length-1);
out += " macro1 program='" + program + "' macroVal='" + macroVal + "'";
}
out += "\">";
out += text;
out += "</span>";
console.log("out " + out);
$("p").on("click" , "span.macro1" , function(e)
{
BqlUtil.myFunction(program, macroVal);
});
}else{
var out = text;
}
return out;
};
console.log of out give me this
<span class="macro consolas-text macro1 program='test1' macroVal='test2'">{TEST}</span>
I have tried both this.program and program but it doesn't work.
Obtain values of span element attributes, since you include them in html:
$("p").on("click" , "span.macro" , function(e)
{
BqlUtil.myFunction(this.getAttribute("program"),
this.getAttribute("macroVal"));
});
There are, however, several things wrong in your code.
you specify class attribute twice in html assigned to out,
single quotes you use are not correct (use ', not ’),
quotes of attribute values are messed up: consistently use either single or double quotes for attribute values
var out = "<span class='";
...
out += "' class='macro' program='" + program + "' macroVal='" + macroVal + ;
...
out += "'>";
depending on how many times you plan to call onClickTest, you may end up with multiple click event handlers for p span.macro.

Call a javascript function from anchor tag inside td inside javascript code

Only Basic javascript knowledge is required.If anyone knows please help me.
I don't know how to do it but i have tried it in many ways but still not able to pass the value.
Simply, i have a for loop and i have a td inside it. I want to call a javascript function from this td click but problem is i am unable to pass any parameter to this function.
the code is here :
function GetContractList(abc) {
var data = abc
for (var it in data) {
tab += "<tr>";
tab += "<td>" + data[it].ContractCode + "</td>";
if (data[it].ContractCode != "") {
var Contract = data[it].ContractCode;
tab += "<td><a onclick='Delete_User(Contract);'>View</td>";
// tab += "<td><a data=" + data[it].ContractCode + " href='javascript:Delete_User(this.data);'>View</td>";
}
else {
tab += "<td></td>";
}
As u can see, i have tried to pass parameter to Delete_User function but the syntax is somewhere broken.
tab += "<td><a onclick='Delete_User(Contract);'>View</td>";
this line gives error-- Contract is not defined.
"<td><a data=" + data[it].ContractCode + " href='javascript:Delete_User(this.data);'>View</td>".
This line also doesnot passes any value to the function.
Please someone help me out.
try:
var cont = data[it].ContractCode.replace(/"/g, '\\"');
tab += '<td><a onclick="Delete_User(\''+cont+'\');">View</td>";
first line encodes any double quotes
the second line inserts the contract as a parameter and adds single quotes around it
You need to escape the quote for the parameter of the function.
tab += '<td>View</td>';
// ^^ ^^
function Delete_User(id) {
console.log('Delete_User', id);
}
var cc = '4711abc',
tab = 'View';
document.write(tab);

Uncaught ReferenceError: is not defined onclick when using character strings

I am trying to pass a variable to the onClick function using a previously stored value. I have a database setup that searches for store locations when provided with a ZIP code. For example, the following link is generated using an ajax call after a user searches for a Zip Code. The returned value "WAFHOH3" is the ID that is associated with that particular store:
Generated Link:
<input type="button" onclick="myfunction(WAFHOH1);" value="This Is My Store" data-store-code="WAFHOH3">
Based on this code:
<div class="col-sm-3"><input type="button" onclick="myfunction(' + item.store_code + ');" value="This Is My Store" data-store-code="' + item.store_code + '"></div>
My problem is that if anything other than a number is returned I get a "Uncaught ReferenceError: WAFHOH3 is not defined" console error. When a number is passed like the example below, everything works fine and I get no errors and the application continues to work as expected.
For example (This Works):
Ive tried manually changing the character string to numbers only to isolate any database related issues. My only guess is that there is something in my code that is maybe attempting to verify the input as number.
The full code is below for the ajax call.
Full Code:
function myFunction() {
var searchValue = $('#foobar').val();
if (searchValue.length > 3) {
var acs_action = 'searchCction';
$.ajax({
async: false,
url: mysearchurl.url+'?action='+acs_action+'&term=' + searchValue,
type: 'POST',
data: {
name: searchValue
},
success: function (results) {
var data = $.parseJSON(results);
$('#resContainer').hide();
var html = '';
if (data.length > 0) {
html += '<br/><br/><ul>';
for (var i = 0; i < data.length; i++) {
var item = data[i];
html += '<li>';
html += '<div class="row myclass">';
html += '<div class="col-sm-9">';
html += ' <h3>' + item.label + '</h3>' ;
html += ' <span>' + item.desc + '</span>';
html += '</div>'
html += ' <div class="col-sm-3"><input type="button" onclick="dofunction(' + item.store_code + ');" value="This Is My Store" data-store-code="' + item.store_code + '"></div>';
html += '</div>';
html += '</li>';
}
html += '</ul><br/><br/><p>This is an example message please email us at admin#admin.com for assistance.';
}
else {
html += '<br/><br/><p>This is an example message, email us at admin#admin.com for assistance.';
}
$('#foo').html(html);
$('#foo').show();
$('.foobar').hide();
}
});
} else {
$('#foo').hide();
}
}
You need to wrap the input item.store_code with quotation marks; otherwise, it tries to treat it as a variable, not a string:
html += '<div class="col-sm-3"><input type="button" onclick="noActivationCodeRegistration(\'' + item.store_code + '\');" value="This Is My Store" data-store-code="' + item.store_code + '"></div>';
Ideally, you would attach a click handler after giving the buttons a class (such as register):
html += '<div class="col-sm-3"><input type="button" class="register" value="This Is My Store" data-store-code="' + item.store_code + '"></div>';
// Later
$('.register').on('click', function() {
var storeCode = $(this).data('storeCode');
noActivationCodeRegistration(storeCode);
});
I may be late, and maybe its an absolute mistake of me, but, i have to add my answer here because i just solved exactly the same situation in about three minutes ago .
I just solved this using the most simple sollution, and the error "Uncaught ReferenceError" from the console is solved, also i have my alert(); passing the variable as i needed.
I also need to include that i did not aproove the sollution gave, about "not using" the alert function, once i searched for the sollution, not for another method for that .
So, as i am using php, and the document is html, i thinked about the apostrophe charactere to the variable, after i had been spectating the element using chrome, first moving the function alert to the parent and child elements, that not solved .
After, also in the specting element, inside chrome F12 i tryed changing the function, including '' (that i passed in php code) into variable inside the alert function as: onclick="alert(variable);" to onclick="alert('variable');" and my alert had worked .
Ok. So, i try everything to insert '' 2 single quotes '' to my variable in php, that seems impossible, even if i change all my code to " and use ' or the oposite .
Then, i decided to try the most obvious and old school method, that is about charactere representation, and i cfound that ' (single quote) is represented by ' in php. Everything inside ->> ' <<-
My php code is like this : onclick="alert(&#039'.$variable.'&#039);"
It will work! (with no Vue), ok ? :)

Uncaught ReferenceError: function is not defined with onclick

I'm trying to make a userscript for a website to add custom emotes. However, I've been getting a lot of errors.
Here is the function:
function saveEmotes() {
removeLineBreaks();
EmoteNameLines = EmoteName.value.split("\n");
EmoteURLLines = EmoteURL.value.split("\n");
EmoteUsageLines = EmoteUsage.value.split("\n");
if (EmoteNameLines.length == EmoteURLLines.length && EmoteURLLines.length == EmoteUsageLines.length) {
for (i = 0; i < EmoteURLLines.length; i++) {
if (checkIMG(EmoteURLLines[i])) {
localStorage.setItem("nameEmotes", JSON.stringify(EmoteNameLines));
localStorage.setItem("urlEmotes", JSON.stringify(EmoteURLLines));
localStorage.setItem("usageEmotes", JSON.stringify(EmoteUsageLines));
if (i == 0) {
console.log(resetSlot());
}
emoteTab[2].innerHTML += '<span style="cursor:pointer;" onclick="appendEmote(\'' + EmoteUsageLines[i] + '\')"><img src="' + EmoteURLLines[i] + '" /></span>';
} else {
alert("The maximum emote(" + EmoteNameLines[i] + ") size is (36x36)");
}
}
} else {
alert("You have an unbalanced amount of emote parameters.");
}
}
The span tag's onclick calls this function:
function appendEmote(em) {
shoutdata.value += em;
}
Every time I click a button that has an onclick attribute, I get this error:
Uncaught ReferenceError: function is not defined.
Update
I tried using:
emoteTab[2].innerHTML += '<span style="cursor:pointer;" id="'+ EmoteNameLines[i] +'"><img src="' + EmoteURLLines[i] + '" /></span>';
document.getElementById(EmoteNameLines[i]).addEventListener("click", appendEmote(EmoteUsageLines[i]), false);
But I got an undefined error.
Here is the script.
I tried doing this to test if listeners work and they don't for me:
emoteTab[2].innerHTML = '<td class="trow1" width="12%" align="center"><a id="togglemenu" style="cursor: pointer;">Custom Icons</a></br><a style="cursor: pointer;" id="smilies" onclick=\'window.open("misc.php?action=smilies&popup=true&editor=clickableEditor","Smilies","scrollbars=yes, menubar=no,width=460,height=360,toolbar=no");\' original-title="">Smilies</a><br><a style="cursor: pointer;" onclick=\'window.open("shoutbox.php","Shoutbox","scrollbars=yes, menubar=no,width=825,height=449,toolbar=no");\' original-title="">Popup</a></td></br>';
document.getElementById("togglemenu").addEventListener("click", changedisplay,false);
Never use .onclick(), or similar attributes from a userscript! (It's also poor practice in a regular web page).
The reason is that userscripts operate in a sandbox ("isolated world"), and onclick operates in the target-page scope and cannot see any functions your script creates.
Always use addEventListener()Doc (or an equivalent library function, like jQuery .on()).
So instead of code like:
something.outerHTML += '<input onclick="resetEmotes()" id="btnsave" ...>'
You would use:
something.outerHTML += '<input id="btnsave" ...>'
document.getElementById ("btnsave").addEventListener ("click", resetEmotes, false);
For the loop, you can't pass data to an event listener like that See the doc. Plus every time you change innerHTML like that, you destroy the previous event listeners!
Without refactoring your code much, you can pass data with data attributes. So use code like this:
for (i = 0; i < EmoteURLLines.length; i++) {
if (checkIMG (EmoteURLLines[i])) {
localStorage.setItem ("nameEmotes", JSON.stringify (EmoteNameLines));
localStorage.setItem ("urlEmotes", JSON.stringify (EmoteURLLines));
localStorage.setItem ("usageEmotes", JSON.stringify (EmoteUsageLines));
if (i == 0) {
console.log (resetSlot ());
}
emoteTab[2].innerHTML += '<span style="cursor:pointer;" id="'
+ EmoteNameLines[i]
+ '" data-usage="' + EmoteUsageLines[i] + '">'
+ '<img src="' + EmoteURLLines[i] + '" /></span>'
;
} else {
alert ("The maximum emote (" + EmoteNameLines[i] + ") size is (36x36)");
}
}
//-- Only add events when innerHTML overwrites are done.
var targetSpans = emoteTab[2].querySelectorAll ("span[data-usage]");
for (var J in targetSpans) {
targetSpans[J].addEventListener ("click", appendEmote, false);
}
Where appendEmote is like:
function appendEmote (zEvent) {
//-- this and the parameter are special in event handlers. see the linked doc.
var emoteUsage = this.getAttribute ("data-usage");
shoutdata.value += emoteUsage;
}
WARNINGS:
Your code reuses the same id for several elements. Don't do this, it's invalid. A given ID should occur only once per page.
Every time you use .outerHTML or .innerHTML, you trash any event handlers on the affected nodes. If you use this method beware of that fact.
Make sure you are using Javascript module or not?!
if using js6 modules your html events attributes won't work.
in that case you must bring your function from global scope to module scope. Just add this to your javascript file:
window.functionName= functionName;
example:
<h1 onClick="functionName">some thing</h1>
I think you put the function in the $(document).ready.......
The functions are always provided out the $(document).ready.......
I got this resolved in angular with (click) = "someFuncionName()" in the .html file for the specific component.
Check the casing of your functions.
onclick="sillyLongFunctionName"
and
function sillylongFunctionName() { ...
Are not identical. Hard to spot sometimes!
If the function is not defined when using that function in html, such as onclick = ‘function () ', it means function is in a callback, in my case is 'DOMContentLoaded'.
See that your function is not in a callback function if you are using an external js file.
Removing the callback function would do the trick
(function() { //comment this out
//your code
})(); //comment this out

Categories