Passing arguments when setting onclick in Javascript - javascript

Alright, i've been looking everywhere for a way to do that.
I have a list of buttons that are supposed to delete a table row when they are clicked on. I can't write a onclick directly in the HTML file because some of those table row can be added or deleted by the user, so I added them in Javascript:
function setOnclick() {
var deleteBtn = document.getElementsByClassName("delete-btn");
for(var i = 0; i < deleteBtn.length; ++i){
deleteBtn[i].onclick = deleteArticle(/*(this)*/);
}
}
function deleteArticle(article){
/* delete the article row from table */
}
Now I cannot put any arguments because if I put () at the end of the function it's going to launch it instead of just assinging it.
PS: Since this is an assignment, I'm not authorized to use jQuery.1

If you want to pass arguments to event listener, .bind() can be used:
function setOnclick() {
var deleteBtn = document.getElementsByClassName("delete-btn");
for(var i = 0; i < deleteBtn.length; ++i){
deleteBtn[i].onclick = deleteArticle.bind(deleteBtn[i], 'some_more_parameter');;
}
}
function deleteArticle(param){
// DOM operation with "this"
alert(this.innerText + ' & ' + param);
}
setOnclick();
<button class="delete-btn">
xxx
</button>
<button class="delete-btn">
yyy
</button>

you should put
...
deleteBtn[i].onclick = deleteArticle
...
function deleteArticle(){
this.parentNode.removeChild(this);
}

You can use clouser function.
function setOnclick() {
var deleteBtn = document.getElementsByClassName("delete-btn");
for(var i = 0; i < deleteBtn.length; ++i){
let article = deleteBtn[i];
article.onclick = function() {
deleteArticle(article);
}
}
}
function deleteArticle(article){
/* delete the article row from table */
}

Related

Javascript created button, get id of the button pressed with onclick(

Note: this is my first project, sorry if this is obvious, I've looked everywhere and can't find it
I'm working on a website that would serve as a better UI then file explorer/VLC, so I've made a button where you can upload all your video files. With those file, my Javascript has a for loop to create a button for each individual video found in that directory, then it puts the name of the file in the button. And all that works, now what I'm struggling with is creating an onclick event that gets the ID of the button that was pressed. I'm really struggling on doing this so any help would be appreciated.
My javascript:
var animepaths = [];
var animenames = [];
//FILE UPLOADING
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
const fileList = event.target.files;
filesLoop(fileList)
});
//loops through every file found in the directory
//and saves the path and file name to local storage
function filesLoop(files){
for(var x = 0; x < files.length; x++){
animepaths.push(files[x].webkitRelativePath)
animenames.push(files[x].name)
}
printOnScreen(animenames, animepaths)
}
//Creating a button with an H2 tag inside
//Then display it on screen in the container (display grid)
function printOnScreen(animenames, animepaths){
for(var x = 0; x < animenames.length; x++){
const elem = document.createElement('button');
elem.classList.add("grid-item");
const elemtext = document.createElement('h2')
elemtext.innerHTML = animenames[x]
elemtext.classList.add("grid-innertext")
elem.appendChild(elemtext)
document.getElementById('container').appendChild(elem);
}
}
If you have more than 1 button you should identify the group of buttons via a class not an id.
in your case it's even easier, as you create the button pro grammatically, so we could create the event there ...
//your function and some of my code
function printOnScreen(animenames, animepaths){
for(var x = 0; x < animenames.length; x++){
createAndAppendButton(animenames[x], animepaths[i]);
}
}
function createAndAppedButton(name, path) {
let button = document.createElement('button');
button.classList.add("grid-item");
button.innerText = name
document.getElementById('container').appendChild(button);
button.addEventListener("click", function() {
//do something with the path, which is accessible her
console.log(path)
});
}
As you can see I removed your h1, as H1 cannot be a child of the button-tag
In any DOM event handler, the element that triggered the event is available within the handler via the this keyword. Therefore, to get the id of the button that triggered the event, you'd just use: this.id.
Here's an example:
document.querySelector("button").addEventListener("click", function(){
console.log("The button's id is: " + this.id);
});
<button id="btn">Click Me</button>
Maybe you can use something like:
function onClick(animenameId) {
...
// your magic here
...
}
function printOnScreen(animenames, animepaths){
...
elem.onclick = onClick(animenames[x]);
...
}
What do you think?

JavaScript: add an Eventlistener, that executes a function using the elements Parameter

I have a list of html elements, that have an attibute taskNr.
What I'm trying to achieve: when one of those elements is clicked, another element should be deleted. The id of the element to delete is "task" and the taskNr from the clicked element.
I have tried this:
var tasknumbers = [];
// fügt eventlistener für button removetask hinzu
function activateremovetasklistener(){
var removeBtns = document.getElementsByClassName("fa fa-times-circle floatright fa-fw notfirst");
for (i = 0; i < removeBtns.length; i++) {
tasknumbers[i] = removeBtns[i].getAttribute("taskNr");
removeBtns[i].addEventListener("click", function() {removeTask(i);});
};
}
//entfernt Task bei Klick auf X
function removeTask(index){
var taskNr = tasknumbers[index];
var taskClass = document.getElementById("task" + taskNr);
taskClass.remove();
}
Instead of the taskNr of the element having the Eventlistener it uses the tasknr from the Array.
How do I fix this?
It seems like you are overwriting tasknumber. Remove tasknumber from the click function, I guess this should work!
for (i= 0; i< removeBtns.length; i++) {
var tasknumber = removeBtns[i].getAttribute("taskNr");
removeBtns[i].addEventListener("click", function() {
var taskClass = document.getElementById("task" + tasknumber);
taskClass.remove();
});
};
The problem is, that the Funktion gets the wrong Parameter. this Can be solved by giving it the Event, causing the Eventlistener to be activated, as parameter. So you can get the right taskNr inside the function.

How to instantiate buttons in a HTML table, whose role is to call a JS function in the scope

I'd like to pass a function as parameter in JavaScript,
that function is a reference onto a function stored globally
alertHello = function() {
alert("Hello")
}
for instance, I'd like to create a table from JSON array, which has an actions embedded array.
So I'd like to pass each function stored in actions attribute in my JSON object like this :
{
...
actions : [
{func : alertHello, icon : myIcon}
]
}
So when I create the table, I add a column based on the actions attributes :
for(var i = 0; i < actions.length ; i++)
{
body += "<button class='ui primary icon button' onclick="+actions[i].func+"><i class='"+actions[i].icon+" icon'></i></button>";
}
But I got a "function statement requires a name" error
Actually, I figured out that a 'wrapping function' was what I was looking for,
and I needed to pass the function name as String in the wrapping function this way :
var actions = [ { func : 'sayHello', icon : 'edit' }]
I created a simple wrapping function (notice that this works only on client side) :
wrapFunc = function(func)
{
var fn = window[func];
fn();
}
And then when I've to build the table :
body += "... onclick=wrapFunc('"+actions[i].func+"')><i class='"+actions[i].icon+" icon'></i></button>";
Finally, when the page is loaded, the function will only be triggered once I'll click the specific button.
I hope this could help other folks. By the way, my question was not completely relevant.
I see no definition for body, nor do I think += will work. Additionally, the function should not be wrapped in quotes or with pluses. Try this:
var body = document.getElementsByTagName('body')[0]
for(var i = 0; i < actions.length ; i++) {
var btn = document.createElement('button');
btn.className = 'ui primary icon button';
btn.onclick = actions[i].func();
var i = document.createElement('i');
btn.appendChild(i);
i.className = actions[i].icon;
}
You may also need to add var to your alertHello definition, like this:
var alertHello = function() {
alert("Hello")
}
Here's a fiddle: https://jsfiddle.net/17ex1ksr/1/
for(var i = 0; i < actions.length ; i++)
{
body += "<button class='ui primary icon button' onclick="+actions[i].func+"()><i class="+actions[i].icon+" icon></i></button>";
}
This should work since actions is a global array, however your quotation marks seem to be out of place. So, inside your loop, instead of
<... onclick="+actions[i].func+" ...>
do
<... onclick='actions[" + i + "].func()' ...>`
This will render:
<button onclick='actions[0].func()'> ...
<button onclick='actions[1].func()'> ...
<button onclick='actions[2].func()'> ...
Example: Function as OnClick Parameter.

remove this.class function Javascript

I have a function connected to a class, that lets me remove it by className.
the problem I have is when I have two elements with the same class name. the function close both of the classes and not only the one that's selected.
I think that i use use a element.this function, but when I try it, none of the classes removes.
Any ideas ?
function CloseEvent(){
var CloseEvent = "close";
var addClassArr= document.getElementsByClassName(CloseEvent);
for(var i=0; i<addClassArr.length; i++){
var addClass = addClassArr[i];
addClass.addEventListener("click", closebutton, true);
}
function closebutton() {
var classToRemove = "dice-window-wrapper";
var elems = document.getElementsByClassName(classToRemove);
for (var i = 0; i < elems.length; i--) {
elems[i].parentNode.removeChild(elems[i])
}
}
}
CloseEvent();
the function close both of the classes and not only the one that's selected.
That's wrong, since more than one are selected via document.getElementsByClassName - and all of them are removed correctly.
Instead of selecting elements by their class name, select the one on which the event was fired at.
function closebutton(e) {
var elem = e.target; // or just the "this" keyword
// elem is the <div class="close" />
var wrapper = elem.parentNode.parentNode;
// wrapper is the <div class="dice-window-wrapper" />
wrapper.parentNode.removeChild(wrapper);
}
Updated the html code to reflect the html used on your site.
<div class="dice-window-wrapper">
<div class="dice-menubar-wrapper">
<div class="close">
close one
</div>
</div>
</div>
<div class="dice-window-wrapper">
<div class="dice-menubar-wrapper">
<div class="close">
close one
</div>
</div>
</div>
then here is how to remove the clicked element:
function CloseEvent(){
var CloseEvent = "close";
var addClassArr= document.getElementsByClassName(CloseEvent);
for(var i=0; i<addClassArr.length; i++){
var addClass = addClassArr[i];
addClass.addEventListener("click", closebutton, true);
}
function closebutton(e) {
var classToRemove = " "+"dice-window-wrapper"+" ";
var obj=e.target;
while((" "+obj.className+" ").indexOf(classToRemove)==-1){
obj=obj.parentNode;
}
if(obj.tagName.toLowerCase()!="div"){
console.log("something wrong in closebutton");
return;
}
obj.parentNode.removeChild(obj);
}
}
Note that this doesn't work at all in IE8 because getElementsByClassName is not supported not is the event passed in this way and there might be a problem with addEventListner. That's why I usually use jQuery.
You should be able to identify the object calling a JS function by using this to identify the triggering element like
function closebutton() {
this.parentNode.removeChild(this);
}
e.g. Delete the SO logo!
function notSO(){this.parentNode.removeChild(this);}
document.getElementById("hlogo").addEventListener("mouseover", notSO, true);
Here's your modified code:
function CloseEvent(){
var CloseEvent = "close";
var addClassArr= document.getElementsByClassName(CloseEvent);
for(var i=0; i<addClassArr.length; i++){
var addClass = addClassArr[i];
addClass.addEventListener("click", function(){ closebutton(this) }, true);
}
function closebutton( elem ) {
var classToRemove = "dice-window-wrapper";
//var elems = document.getElementsByClassName(classToRemove);
//for (var i = 0; i < elems.length; i--) {
// elems[i].parentNode.removeChild(elems[i])
//}
// you have passed the element to be removed, directly remove it
elem.parentNode.removeChild(elem);
}
}
CloseEvent();

Dynamicaly Creating a Table with document.createElement and add onclick functions to each tr

I want to add Rows to a Table that already exists and each row has a onclick attribute. The problem is that each row needs to call the function with another parameter. At The moment no matter in what row i click the function is called with the parameter of the last row in the table.
This is how i add the rows to the table :
table = document.getElementById('ProgramTable');
table.style.visibility = "visible";
tableBody = document.getElementById('ProgrammTableBody');
tablelength = jsonObj0.data.map.programs.length;
// Check if there is already a Table, if so
// remove the Table
if (tableexists) {
removetable();
}
for ( var i = 0; i < tablelength; i++) {
channel = jsonObj0.data.map.programs[i].programServiceName;
frequency = jsonObj0.data.map.programs[i].programIdentifier;
imagelink = "../image/image.jsp?context=tuner&identifier="
+ channel;
var row = document.createElement("tr");
row.setAttribute("id", i);
row.onclick = function() {
tuneProgram(frequency)
};
var channelCell = document.createElement("td");
var imageCell = document.createElement("td");
var imageElement = document.createElement("IMG");
var frequencyCell = document.createElement("td");
channel = document.createTextNode(channel);
frequency = document.createTextNode(frequency);
channelCell.appendChild(channel);
frequencyCell.appendChild(frequency);
imageElement.setAttribute("src", imagelink);
imageElement.setAttribute("width", "40");
imageElement.setAttribute("height", "40"); // TODO OnError
// hinzufügen und evtl
// Css Style für Texte
// siehe Tabellencode
imageCell.appendChild(imageElement);
row.appendChild(channelCell);
row.appendChild(frequencyCell);
row.appendChild(imageCell);
tableBody.appendChild(row);
}
So the tune function should be called with the specific frequency parameter but it seems like he is overwriting the onclick parameter everytime so the last one is in there for every row. But why is that so? is he adding the onclick Attribute to every row in that table? I don't get it.
Thanks for your help!
Replace
row.onclick = function() {
tuneProgram(frequency)
};
with
row.onclick = (function(frequency) {return function() {tuneProgram(frequency);};})(frequency);
This "anchors" the value of frequency by creating a new closure for it.
You need to do something like this:
for (var i = 0; i < tablelength; i++) {
(function(i) {
//your code here
})(i);
}
Frequency is being referenced when you click - so if the variable changes, it changes every click element. For example, the first row sets a frequency of one and the last row sets a frequency of two. When the onclick runs it isn't referenced to a value, its referenced to a variable in the chain and gets the current value of two.
because your frequency is a global value, so there is only one frequency that every function refer to it;you can cache it in a closure
something like this:
var programTable = document.getElementById('ProgramTable');
programTable.style.visibility = "visible";
programmTableBody = document.getElementById('ProgrammTableBody');
tablelength = jsonObj0.data.map.programs.length;
if (tableexists) {
removetable();
}
function newTabRow ( table, name, identifier ) {
var link = "../image/image.jsp?context=tuner&identifier=" + name,
row = table.insertRow();
row.innerHTML = '<td>' + name + '</td><td><img width="40" height="40" src="'+link+'" alt="''" /></td><td>'+ identifier +'</td>';
row.onclick = function ( ) {
tuneProgram ( identifier );
}
}
for (var i = tablelength; i-- > 0; ) {
program = jsonObj0.data.map.programs[i];
newTabRow ( programTable, program.programServiceName, program.programIdentifier );
}
Be careful I have a function on top of my page with name "show_field_setting". my function get to value and do something. I have a for loop and in my loop i change 'type' and 'id' for each element. you can see one part inside of my for loop below. finally I add my new element to my div with element id 'my_element_id'. If you want to set a function to your created element you need use something like this:
var new_child = document.createElement('div');new_child.id = id;
new_child.href = "javascript:;";
new_child.onclick = (function (type, id) {
return function() {
show_field_setting (type, id);
};
})(type, id);
document.getElementById('my_element_id').appendChild(new_child);
if you have on argumant in your function only, use this:
var new_child = document.createElement('div');
new_child.href = "javascript:;";
new_child.onclick = (function (your_value) {
return function() {
your_function_name (your_value);
};
})(your_value);
document.getElementById('your_element_id').appendChild(new_child);
finally i don't know why. any way if you are not in loop condition like "while", "for" or even "switch" you can use easy below code line:
var new_child = document.createElement('div');
new_child.href = "javascript:;";
new_child.onclick = function(){your_function_name (your_value_1, your_value_2 , ...)};
document.getElementById('your_element_id').appendChild(new_child);
Have Fun ;) :)

Categories