element.onclick not doesn't call function when element is clicked - javascript

I am building a Modal dynamically. I want to make some buttons in this modal to open a SubModal. The buttons show up in html, but clicking these buttons does nothing.
Here is my code.
const subtaskList = document.getElementById('subtaskList');
for (const subtaskIndex in task.subtasks) {
const subtaskButton = document.createElement('button');
subtaskButton.classList.add('taskModalSubtaskButton');
subtaskButton.onclick = () => {
openSubTaskModal(task.subtasks[subtaskIndex], task);
}
subtaskButton.innerText = task.subtasks[subtaskIndex].name;
subtaskList.appendChild(subtaskButton);
subtaskList.innerHTML += '<br>';
}
While troubleshooting I made an array to hold the buttons and used console.log() to see its elements. They all had the onclick function. I've clicked the buttons from the dev console by getting their class name and nothing, so I know it's not a display issue. I feel like I am misunderstanding something and any help would be appreciated.

The problem is subtaskList.innerHTML += '<br>'; it is good idea to use subtaskList.appendChild(document.createElement("br")); instead.
Here is working snippet:
function doSomething(url) {
alert(url);
}
const subtaskList = document.getElementById('subtaskList');
for (var i = 0; i < 3; i++) {
const subtaskButton = document.createElement('button');
subtaskButton.classList.add('taskModalSubtaskButton');
subtaskButton.innerText = "name" + i;
subtaskButton.onclick = (function (url) {
return function () {
doSomething(url);
};
})("URL #" + i)
subtaskList.appendChild(subtaskButton);
subtaskList.appendChild(document.createElement("br"));
}
<div id="subtaskList"></div>
Also I change a bit onclick function to send correspond index to doSomething function

Related

Script that change the HTML-content of another page?

On my first page I have two input boxes and a button that will add the input to localStorage. When the data has been added I want to trigger an event that will write out the contents of localStorage on ANOTHER page. My problem is that my script can't find the element on the second page.
Code that adds the data to localStorage:
$("#submitLocal").click(function () {
var key = inputKey.value;
var value = inputValue.value;
localStorage.setItem(key, value);
if (newWindow == null || newWindow.closed) {
newWindow = window.open("local.html", "localWindow");
}
window.dispatchEvent(new Event("storage"));
});
I add the event listener:
window.addEventListener("storage", myFunc);
Which calls the function:
function myFunc(event) {
document.getElementById("addInfo").innerHTML = "";
for (var i = 0; i < localStorage.length; i++) {
$("#addInfo").append(
localStorage.key(i) +
" " +
localStorage.getItem(localStorage.key(i)) +
"<br>"
);
}
}
Right now, the element "addInfo" is on the FIRST page, and the data in localStorage gets written out on the page. But how can I do to write it on the second page if it cant find the elements on that page?
Im new to stackoverflow so I hope I managed to describe the problem well enough.
Thanks in advance.
It ALWAYS helps to post relevant code. In this case what is $("#submitLocal") ? If it is a submit button in a form, use the form submit event and preventDefault!
Why dispatch events in an event?
Just use the one you are in and the load event in page2
main page
$("#myForm").on("submit", function (e) {
e.preventDefault();
var key = inputKey.value;
var value = inputValue.value;
localStorage.setItem(key, value);
if (newWindow == null || newWindow.closed) {
newWindow = window.open("local.html", "localWindow");
}
});
local.html
function myFunc(event) {
$("#addInfo").empty();
for (var i = 0; i < localStorage.length; i++) {
$("#addInfo").append(
localStorage.key(i) +
" " +
localStorage.getItem(localStorage.key(i)) +
"<br>"
);
}
}
window.addEventListener("load",myFunc)

Functions on "newly" created objects in Javascript

Sorry for the title i don't know how to explain it differently.
I created a popup window, there is an "x" close button on right top, advanced and close button on mid bottom. After clicking and replacing text in HTML those newly created buttons just doesn't work.
let mda = document.getElementById("popup");
document.addEventListener("DOMContentLoaded", () => { //show the pop up after loading the stie
mda.style.display = "block";
});
const adv = document.querySelector(".adv"); //Advanced button
let mdc = document.querySelector(".popup-content"); //Pop up content block that changes
adv.onclick = () => {
mdc.innerHTML =
'<span class="close"></span>' + ' ... ' +
'<button class="back">Go back</button>' +
'<button class="closebtn">Go to site</button>'; //Here it creates same button as before
// I thought since it has the same class name it would work but it doesn't,
// tried with simple onclick function but it doesn't work either.
const back = document.querySelector(".back");
back.onclick = () => {
mdc.innerHTML =
'<span class="close"></span>' +
'<button class="adv">Advanced</button>' + //creates adv button again but doesn't work
'<button class="closebtn">Go to site</button>';
};
};
const xbtn = document.querySelector(".close");
const cbtn = document.querySelector(".closebtn");
const close = () => {
xbtn.onclick = () => {
mda.style.display = "none";
};
cbtn.onclick = () => {
mda.style.display = "none";
};
};
close();
I tried everything I could come up with, adding onclick=() to the buttons, addEventListener instead of onclick functions...
Also one weird thing that's happening is if i use getElementByClass or Id instead of query selector those close functions stops working... Please can someone guide me how am i supposed to do it correctly? BTW can't use any libraries.

Dynamically create buttons in js/html based on object state

I have the following situation which I cannot solve. I am relatively new to js. I have a js that runs on a webpage. The script runs when a KB shortcut is pressed. After modifying a few things, it pops up an html banner in which I want to put certain messages and buttons depending on what thing the user ran a script on. For a simple case, let's say there are two potential messages that can go in this popup. I have the details in an object array:
NH_Bann = {
STC: {
active: false,
bannText: "Force Title Case: ",
id: "toTitleCaseStrong",
value: "Yes",
action: function() {
var newNameStr = toTitleCaseStrong(vname);
if (newNameStr !== name) {
//**update function
NH_Bann.STC.active = false;
}
}
},
DTC: {
active: false,
bannText: "Enable DTC? ",
id: "addDTC",
value: "Yes",
action: function() {
//**update function
NH_Bann.DTC.active = false;
}
}
}
When the script is run, there are some if statments that can change the active keys to true. After the script runs, I want to run through the objects in NH_Bann, and if the active key is true, make a message with an action button that fires the action button. The part I am having trouble with is making the buttons dynamically. From other threads, I thought I could store the buttons in an array, but maybe the onclick doesn't work that way? This is what I have:
function setupButtons() {
var ixButt = 0;
var btn = [];
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
btn[ixButt] = document.getElementById(NH_Bann[tempKey].id);
btn[ixButt].onclick = function(){
NH_Bann[tempKey].action();
assembleBanner(); // makes the html for the banner
}
ixButt++;
}
}
}
I make the buttons in another piece of code which sets up the ids:
function assembleBanner() {
sidebarMessageEXT = [sidebarMessage.slice(0)];
var EXTOption = false;
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
sidebarMessageEXT.push(NH_Bann[tempKey].bannText + '<input id="' + NH_Bann[tempKey].id + '" type="button" value="' + NH_Bann[tempKey].value + '">');
EXTOption = true;
}
}
if (EXTOption) {
sidebarMessageEXT = sidebarMessageEXT.join("<li>");
displayBanners(sidebarMessageEXT,severity);
setupButtons();
} else {
displayBanners(sidebarMessage,severity);
setupButtons();
}
}
The issue i'm having is that I get the two distinct messages and two buttons in the banner if both objects are active==true, but pressing them always fires the update function of the DTC object. Any suggestions? I'm open to other methods, but I need to be able to add to the object list over time and have the buttons be displayed conditionally on the status of the active key for each object. Thx!
The problem has to do with closures. In this code:
function setupButtons() {
var ixButt = 0;
var btn = [];
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
btn[ixButt] = document.getElementById(NH_Bann[tempKey].id);
btn[ixButt].onclick = function(){
NH_Bann[tempKey].action();
assembleBanner(); // makes the html for the banner
}
ixButt++;
}
}
}
...tempKey is a variable that lives within the call to setupButtons. Notice that you're creating two onclick function callbacks in a loop, and both make reference to tempKey. However, they're not going to be referencing the variable's value at the time of function creation, but rather the latest value of the variable. So once the loop completes, tempKey is going to reference the last value it had.
To work around this, you can use this trick to create a new closure for each onclick that will have the correct value:
function setupButtons() {
var ixButt = 0;
var btn = [];
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
btn[ixButt] = document.getElementById(NH_Bann[tempKey].id);
btn[ixButt].onclick = (function(buttonId) {
return function() {
NH_Bann[buttonId].action();
assembleBanner(); // makes the html for the banner
}
})(tempKey);
ixButt++;
}
}
}
Essentially, this is binding the current value of tempKey to a new variable by passing it to an immediately-executing function, so both onclick functions no longer reference the variable which changes during the loop.
For a less esoteric way to do this, you could move the creation of each button into its own named function, passing the required data:
function setupButtons() {
var btn = [];
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
btn.push(setupButton(NH_Bann[tempKey]);
}
}
}
function setupButton(bannerData) {
var button = document.getElementById(bannerData.id);
button.onclick = function() {
bannerData.action();
assembleBanner();
};
return button;
}

Click event on every item on populated list with jQuery

Here is how I populate my list:
function bingNetworksList(myList) {
var list = '';
for (i = 0; i < myList.length; i++) {
list += '<li>' + myList[i] + '</li>';
}
$('#myList').empty();
$('#myList').append(list);
}
Here is my html file:
<ul id="myList"></ul>
I want to add a click event for every item of list (without having separate ids):
$(function() {
$('#myList').click(function() {
var listItem = this.find('a').text();
console.log(listItem); // never logged
});
});
However, when I click at a list item, click event doesn't fire.
What am I doing wrong?
I can only assume there's a js error in your console.
I've created a working sample for you. We can use event delegation and then retrieve the DOM node that was clicked. You need to ensure you call the bingNetworksList [assume typo in here and meant binD ;)] function when the DOM ready event has fired.
function bingNetworksList(myList) {
var list = '';
for (i = 0; i < myList.length; i++) {
list += '<li>' + myList[i] + '</li>';
}
$('#myList').empty();
$('#myList').append(list);
}
$(function() {
var list = ["foo", "bar"]
bingNetworksList(list);
$('#myList').click(function(evt) {
var listItem = $(evt.target).text();
console.log(listItem); // never logged
});
});
You need to wrap this inside $ as like this:
$(function() {
$('#myList').click(function() {
var listItem = $(this).find('a').text();
console.log(listItem); // will always be logged
});
});

ng-click not working after first click (embedded directives)

I'm having issues with a button and ng-click. I have an input and a button with and ng-click that when click generates 3 random words. I display this words in a div generated by a directive.
The problem I'm having is that when I click the button the first time the code runs perfectly, but when I click again, the button does nothing, I had to implement a clear button that clears the $scopes and then the generate button works again.
This is the code for my button:
<button class="btn btn-default" type="button" ng-click='generateRandom()'>Generate</button>
Here is the code for the directive:
<div jz-tabs camel='camel' snake='snake' kebab='kebab'></div>
The $scope.generateRandom():
$scope.generateRandom = function() {
var temp = '';
Words.getWords($scope.number)
.then(function(response) {
console.log(response);
response.data.forEach(function(e) {
console.log(e);
temp += ' ' + e.word;
});
$scope.camel = lodash.camelCase(temp);
$scope.kebab = lodash.kebabCase(temp);
$scope.snake = lodash.snakeCase(temp);
});
};
I tried clearing the $scopes inside of the function but it looks like after the first ng-click, the function isn't even been called. Does having embedded directives affect ng-clicks?
Any help with this? I don't want to click "clear" every time I want to generate words, I want them to be able to click generate and get random words every time.
Thank you in advance!
UPDATE: Here is a plnkr of the problem: http://plnkr.co/edit/qGB1VjsIJgBzWKl8tXMt?p=preview
I fixed the problem, I had this two functions:
$scope.generateRandom = function() {
var temp = '';
Words.getWords($scope.number)
.then(function(response) {
for (var i = 0; i < response.data.length; i++) {
temp += ' ' + response.data[i].word
}
$scope.camel = temp;
$scope.kebab = temp;
$scope.snake = temp;
});
};
$scope.clear = function() {
$scope.camel = '';
$scope.kebab = '';
$scope.snake = '';
};
All I had to do was add $scope.clear() at the end of the $scope.generateRandom function and it does the trick.

Categories

Resources