I know the question sounds strange, but it's really very simple. I have the following function which isn't working:
function start40Counter(counter40_set){console.log(counter40_set);
var gid = counter40_set[0];
var seat = counter40_set[1];
var suits = counter40_set[2];
var cont = "";
$.each(suits, function (num, suit) {
cont += "<a class='suitpick' onClick='pickSuit(counter40_set);'><img src='"+base+"images/someimg.png' title='Odaberi' /></a>";
});
$('#game40_picks').html(cont);
}
counter40_set is [10, 3, ["H", "S"]]. The part of the function that fails is the part this:
onClick='pickSuit(counter40_set);'
It says that counter40_set is not defined. I understand that. This wouldn't even work if counter40_set was a simple string instead of an array. If I try onClick='pickSuit("+counter40_set+");' I get a different error, saying H is not defined. I get this too, the array is rendered and JS doesn't know what H and S are.
I also tried passing the array elements (counter40_set[0] etc) individually but it still fails with the last element (["H", "S"]).
So, how do I pass this data to the onClick function in this case? There must be a more elegant way than concatenating the whole thing into a string and passing that to the function?
Btw, this is a simplified version. What I should really be passing in every iteration is [suit, counter40_set] so that each link chooses a different suit. I'm asking the simplified question because that will be enough to send me down the right path.
It cannot work,because the context is lost and thus "counter40_set" is not set.
To fix it simply use jquery for the onlick as well:
$('#game40_picks').empty(); // get rid of everything
$.each(suits, function (num, suit) {
var line = $("<a class='suitpick'><img src='"+base+"images/"+cardsuits[suit].img+"' title='Odaberi "+cardsuits[suit].name+"' /></a>");
line.click(function(ev){
ev.preventDefault(); // prevent default click handler on "a"
pickSuit(counter40_set);
});
$('#game40_picks').append(line);
});
this way the "counter40_set" is available for the click function.
You shouldn't use the onClick HTML attribute. Also, using DOM functions to build nodes saves the time it takes jQuery to parse strings, but basically the method below is to create the element and attach a click event listener and then append it to the specified element.
function start40Counter(event){console.log(event.data.counter40_set);
var counter40_set = event.data.counter40_set;
var gid = counter40_set[0];
var seat = counter40_set[1];
var suits = counter40_set[2];
var cont = "";
$.each(suits, function (num, suit) {
var link = document.createElement('a');
link.className = 'suitpick';
$(link).on('click', {counter40_set: counter40_set}, start40Counter);
var img = document.createElement('img');
img.src= base + "images/" + cardsuits[suit].img;
img.title = 'Odaberi ' + cardsuits[suit].name;
link.appendChild(img);
$('#game40_picks').append(link);
});
}
Not tested but it might work out of the box.
Related
Well this is a thing i need help of some one who know how to get the element from a foreach that innerHTML into a table data that comes from a data base, i did it by this way but it is not the most optimize way, so i need help to do it by other way, i add an onclick event with javascript and the only thing i make by doing this is that the only button that works is the one on top of the table or the bottom button of the table.
This is the way i make it work:
//Preload
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld(
"electron", {
printmovieonpreload: (results) => ipcRenderer.on("send-movie", (event, results) => {
mylist.innerHTML = " "
results.forEach(elements => {
mylist.innerHTML += `<tr><td> ${elements.movie-name} </td>
<td> ${elements.movie-duration} min </td><td><button id="btn" value="${elements.id-movie}" "/*this get all the onclick events of the page*/${onclick = deletefromtable}" type="button" class="fas cli fa-trash-alt"></button></td>
</tr>`;
});
})
});
async function deletefromtable(e) {
/* this is were i filter from id of the onclick event and how i reduce the value of the button to delete it*/
if (e.srcElement.id == "btn") {
const obj = {
id: e.srcElement.value
}
await ipcRenderer.invoke('delete_movie', obj);
}
}
It's better to not do this by string interpolation, but by letting the browser (in Electron's terms, Chromium) create elements of the wanted type and then setting their contents and appending them to the parent. This can (and should) be done like so:
// inside your forEach function
var tr = document.createElement ("tr");
var td1 = document.createElement ("td");
var td2 = document.createElement ("td");
var td3 = document.createElement ("td");
var btn = document.createElement ("button");
td1.textContent = elements ["movie-name"];
td2.textContent = elements ["movie-duration"] + " min";
btn.id = "btn";
btn.classList.add ("fas", "cli", "fa-trash-alt");
btn.type = "button";
btn.value = elements ["id-movie"];
btn.onclick = delete_from_table;
td3.appendChild (btn);
tr.appendChild (td1);
tr.appendChild (td2);
tr.appendChild (td3);
myList.appendChild (tr);
For this to work, however, you must meet the following conditions:
The index strings for the elements array must be correct. I'm pretty sure that your code using string interpolation would throw errors, because - is an operator and cannot be used when referencing indices using the dot operator.
delete_from_table must be a function, not a string. Since it is not included in the code snippet you have posted, I cannot verify if my solution would work based off of that. However, it seems that you would rather like to bind updatestatuscero to the onclick event of the button. If so, simply replace delete_from_table with this function's name.
Just some more tips regarding general JavaScript:
Use braces wherever possible to make the code more intelligible. For example, you could have written your code like so:
contextBridge.exposeInMainWorld(
"electron", {
printmovieonpreload: (results) => {
ipcRenderer.on("send-movie", (event, results) => {
mylist.innerHTML = " "
results.forEach(elements => {
mylist.innerHTML += `<tr><td> ${elements.movie-name} </td>
<td> ${elements.movie-duration} min </td><td><button id="btn" value="${elements.id-movie}" "/*this get all the onclick events of the page*/${onclick = delete_from_table}" type="button" class="fas cli fa-trash-alt"></button></td>
</tr>`;
});
});
}
}
});
This way, the scope of the functions can be understood at first glance. Both you and any other person having to work with this code in the future will be very pleased if you keep it organised.
When using string interpolation, you can execute operations. This is why I stated that - is not valid in an index above. The reason for this is that any expression inside ${} in an interpolated string will be evaluated and its return value will be included in the string. Thus,
var testObject = {
"test-prop": "def"
};
var stringA = `abc ${testObject.test-prop} ghi`; // Throws: ReferenceError, prop is not defined
var stringB = `abc ${testObject["test-prop"]} ghi`; // yields "abc def ghi"
What the expression inside stringA tries to do is to actually subtract prop from testObject.test, neither of which are defined.
Also, with string interpolation, you have executed an assignment (${ onclick = delete_from_table}) which caused the new variable onclick to be defined, the method to be (correctly) written to the HTML, but not bound to the buttons' onclick event! Instead, you could have done onclick="${delete_from_table}" just like you did with the value property.
Don't ever insert HTML by using element.innerHTML! Take a look at MDN -- this method has some pretty unexpected implications. Better sanitise your HTML first, use element.insertAdjacentHTML() or simply create elements and add them to a parent element by using element.appendChild() as I showed you above. This way is also, in my opinion, but tastes differ, the cleanest way possible.
I need to pass a value from html and use it to find a var in my Js, so according to the value in theId on my html I could use the var in my js. How can I do that?
HTML
<input id="Waist" type="checkbox" onchange="getToWork(this.id)" >Waist
<script> tag on HTML
function getToWork(theId){
usedCheckBox(theId);
}
myJs.js
function usedCheckBox(theId){
var temp1 = theId.name; - will be undefined
var temp2 = Waist.name; - will work
}
var Waist = {name:"bob",age:"17"}
The problem with your code is, you are not using document.getElementById as below:
JS:
document.getElementById("Waist").addEventListener("change",function(evt){
getToWork(this.id);
})
function getToWork(theId){
usedCheckBox(theId);
}
function usedCheckBox(theId){
console.log(theId);
console.log(Waist);
var temp1 = document.getElementById("Waist").val; // will return Waist
var temp2 = Waist.val(); // generate error, don't know what you want
}
var Waist = "change today!"
Fiddle:
https://jsfiddle.net/xLvzah8w/1/
I understood your question now and for that you should create one parent object as shown:
function usedCheckBox(theId){
var temp1 = parent[theId].name; // will return bob
console.log(temp1);
var temp2 = parent.Waist.name; // will return bob
console.log(temp2);
}
var parent = {
Waist : {name:"bob",age:"17"}
}
The reason why your code doesn't work is because you are trying to access property of a string. 'theId' is a string with value 'Waist' where Waist is an object so error occurs.
Updated fiddle: https://jsfiddle.net/xLvzah8w/2/
The correct way to proceed with this is:
In place of var temp1 = theId.val();
Use document.getElementById(theId).value
When you do: theId.val(), it makes sense that it's undefined. Calling getToWork(this.id) is sending a string, not an HTML element. Therefore calling .val() on a string is undefined.
If you're trying to get the text value stored in the checkbox element that was pressed, you need to change to ...
function getToWork(arg) {
console.log(document.getElementById(arg).value);
}
<input id="Waist" type="checkbox" value="INPUT_BOX" onchange="getToWork(this.id)"> Waist
You should avoid using the onclick attribute and rather listen for the event "js side" (addEventListener/attachEvent).
In the context of those eventhandlers, this generally represents the element the event listener has been attached to:
document.getElementById("Waist").addEventListener("change",getToWork);
function getToWork(){
usedCheckBox(this);
}
function usedCheckBox(elem){
var value = elem.value ;
}
I'm having some difficulty here with getElementById returning a null object. All of the below code has been placed inside an anonymous function that is called when "DOMContentLoaded" (event listener). I did this to avoid getElementById not being able to find the twitter button when I attempt to set an attribute (particularly "data-text"). The first function has no problem locating the element (an 'a' element on the page) with getElementById, but the second function returns null. I thought that running it only after "DOMContentLoaded" would solve this problem? What am I missing here? (please let me know if I'm not putting enough of my code here to show what I'm trying to do.)
//Add initial invisible quote
(function () {
var quoteList = document.querySelector(".hidden-quotes").children;
var randomQuoteNum = Math.round((Math.random() * (quoteList.length - 1)));
var quoteBox = document.getElementById("quote-box");
quoteBox.innerHTML = quoteList[randomQuoteNum].innerHTML;
var tweetQuote = (quoteBox.children[0].innerHTML + " " + quoteBox.children[1].innerHTML);
var tweetButton = document.getElementById("tweet-button");
tweetButton.setAttribute("data-text", tweetQuote);
tweetButton.setAttribute("data-url", " ");
})();
//Set up quote button functionality
var magicButton = document.getElementById("quote-button");
magicButton.addEventListener("click", function () {
var quoteList = document.querySelector(".hidden-quotes").children;
var randomQuoteNum = Math.round((Math.random() * (quoteList.length - 1)));
var quoteBox = document.getElementById("quote-box");
quoteBox.innerHTML = quoteList[randomQuoteNum].innerHTML;
var tweetQuote = (quoteBox.children[0].innerHTML + " " + quoteBox.children[1].innerHTML);
var tweetButton = document.getElementById("tweet-button");
console.log(tweetButton);
tweetButton.setAttribute("data-text", tweetQuote);
quoteBox.style.opacity = 1;
});
Here's the markup:
<a id="tweet-button" class="twitter-share-button" href="https://twitter.com/intent/tweet">Tweet this.</a>
Only the first function seems to be able to access and modify an attribute of the above element, while the second function cannot even find it (getDocumentById returns null).
And here's the codepen.
It looks like the button you set up with the class twitter-share-button is changed a bit by the script that loads it. Try getting it like this.
var tweetButton = document.getElementsByClassName("twitter-share-button")[0];
// plays a card into table.
// this code works. rendered card is appending into the table.
var playCard = function(card){
var renderedCard = renderCard(card);
$('#'+renderedCard.id).appendTo('#flop');
// but this one does not work.
var playCom = function(){
$.post('/api/comPlay', function(data){
var renderedCard = renderCard(data.card);
$('#'+renderedCard.id).appendTo('#flop');
});
};
I check the returned value from $.post. data.card gives the correct value. I create a div html with my renderCard function. That function works correctly as you see. But under $.post not.
I am stuck. Is there something special that i must know about $.post?
Thank you.
update :
var renderCard = function(card){
var create = document.createElement('div');
create.className = 'cardBig';
create.id = card;
return create;
};
You don't need to "find" your newly-created DOM element.
$(renderedCard).appendTo('#flop');
should do it.
Also, since you're using jQuery anyway:
$('#flop').append($('<div/>', {
className: 'cardBig',
id: data.card
}));
will save you the extra function.
In renderCard() method you are just creating a new html element but it is not rendered to the dom.
So your element lookup $('#'+renderedCard.id) will not work
$(renderedCard).appendTo('#flop');
have you tried selecting the id element first, like so:
$(renderedCard).appendTo( $('#flop')[0] )
Lets say that I have a element reference obtained ala...
var x=document.getElementById("ID123");
Now I want to include some function of x on a dynamically created html element ala...
myWin.document.write("<input type='button' data-doit=????? value='Do It' onclick='window.doit(?????);'/>");
so that function doit() can recreate the original reference x
function doit()
{
var x = ?????;
}
Right now I'm doing this by obtaining a numeric index of x as found via getElementsByTagName and passing that as a parameter to doit().
Is there some way to do this?
I would probably pass the ID of x to doit(), which would require doit() to look something like this:
function doit(id) {
var x = document.getElementById(id);
// etc
}
As far as creating the input element goes, there a couple of ways to do this. This is similar to your current solution (but non-standard):
myWin.document.write('<input ... onclick="doit(' + x.id + ');" />');
The standard solution is to create your new input element using the DOM API:
var input = myWin.document.createElement('input');
input.type = 'button';
// other properties
input.onclick = function () {
doit(x.id);
};
// insert new element
document.getElementById("myform").appendChild(input);
(Note that inserting the element is a little more complicated in this situation - you have to programmatically find its location in the DOM).
Finally, if you're using jQuery, you might do something this:
var input = $('<input type="button" etc />').click(function () {
doit(x.id);
});
$('#myform').append(input);