Javascript button.onclick not functioning like I thought - javascript

So I was in the presumption that this function
button.onclick = exampleFunk;
would give me a handler on each button when I click them, but it doesn't. When replacing it with:
button.onclick = alert("bananas");
I'm getting alerts at page onload. The problem is already solved with this:
button.setAttribute("onclick", "removeIssue(this)");
Out of curiousity... What's going on?
edited layout of post
EDIT
var issues = [];
window.onload = function () {
//alert("venster geladen");
issuesToList()
}
function issuesToList(data) {
/*alert(
"array length is " + data.issues.length + "\n" +
"total_count is " + data.total_count + "\n" +
"limit is " + data.limit + "\n" +
"offset is " + data.offset + "\n" + ""
);*/
for (i = 0; i < data.issues.length; i++) {
issue = data.issues[i];
createIssue(issue);
}
}
function createIssue(issue){
var id = issue.id;
var tracker = issue.tracker;
var status = issue.status;
var priority = issue.priority;
var subject = issue.subject;
var description = issue.description;
var assignee = issue.assignee;
var watchers = issue.watchers;
var ticket = new Issue(id, tracker, status, priority, subject, description, assignee, watchers);
issues.push(ticket);
var button = document.createElement("button");
button.innerHTML = "-";
button.onclick = function (){ alert("bananas")};
//button.setAttribute("onclick", "removeIssue(this)");
var item = document.createElement("div");
item.setAttribute("id", id);
item.appendChild(button);
item.innerHTML += " " + subject;
var container = document.getElementById("container");
container.appendChild(item);
}
function removeIssue(e){
var key = e.parentNode.getAttribute("id");
var count = issues.length;
if(confirm("Confirm to delete")){
for(i=0; i<count; i++){
if (issues[i].id == key ){
issues.splice(i,1);
var element = document.getElementById(key);
element.parentNode.removeChild(element);
}
}
}
}
function Issue(id, tracker, status, priority, subject, description, assignee, watchers){
this.id = id;
this.tracker = tracker;
this.status = status;
this.priority = priority;
this.subject = subject;
this.description = description;
this.assignee = assignee;
this.watchers = watchers;
}
EDIT
<body>
<h1>List of Issues</h1>
<div id="container"></div>
<script src="http://www.redmine.org/issues.json?limit=10&callback=issuesToList"></script>
</body>

You need to mask the alert in a function:
button.onclick = function (){ alert("bananas")};
As such:
var btn = document.createElement("BUTTON");
var t = document.createTextNode("CLICK ME");
btn.appendChild(t);
btn.onclick = function() {alert("bananas")};
document.body.appendChild(btn);

Whats going on?
You alert() is executed on page load because its a function call. When the execution of your script reaches that line your assignment
button.onclick = alert("bananas");
is actually executing the alert statement and not assigning it to button.onclick

You can bind arguments to the function so that it returns with the function you want it to call using your arguments (with additional arguments passed later added on to the end). This way doesn't require writing extraneous code (when all you want to do is call a single function) and looks a lot sleeker. See the following example:
button.onclick = alert.bind(window, "bananas");
An unrelated example of how it works in your own code is like this:
var alert2 = alert.bind(window, 'Predefined arg');
alert2(); // 'Predefined arg'
alert2('Unused'); // 'Predefined arg'
For IE, this requires IE9 as a minimum. See MDN for more information.
EDIT: I've looked closer at your code and there was one significant change that was needed for it to work... You cannot add onto the innerHTML when you've added JavaScript properties to a child element. Changing the innerHTML of the parent element will convert your element into HTML, which won't have the onclick property you made before. Use element.appendChild(document.createTextNode('My text')) to add text dynamically.
See a functioning example here: http://jsfiddle.net/2ftmh0gh/2/

Related

removeChild() and addEventListener()

I am trying to make a Library project using vanilla JS and I can't understand the behaviour of removeChild() and addEventListener() in the code.
var myLibrary = [];
var content = document.querySelector(".content");
var nameField = document.createElement("input");
var authorField = document.createElement("input");
var pagesField = document.createElement("input");
var readingStatusField = document.createElement("input");
var submitButton = document.createElement("button");
var form = document.createElement("form");
function Book(name, author, pages, status){
this.name = name;
this.author = author;
this.pages = pages;
this.status = status
}
Book.prototype.info = function(){
if(this.status === false){
return console.log(this.name + " " + "by " + this.author + "," + this.pages + " pages, " + "not read yet" )
}
else{
return console.log(this.name + " " + "by " + this.author + "," + this.pages + " pages, "+ "read" )
}
}
function addBookToLibrary(Book) {
myLibrary.push(Book);
}
function displayBooks(){
for(let x = 0; x < myLibrary.length; x++){
myLibrary[x].info();
}
}
function createBookForm() {
var form = document.createElement("form");
form.classList.add("book-form")
nameField.classList.add("formfield")
nameField.setAttribute("type", "text");
nameField.setAttribute("placeholder", "Name");
authorField.classList.add("formfield")
authorField.setAttribute("type", "text");
authorField.setAttribute("placeholder", "Author");
pagesField.classList.add("formfield")
pagesField.setAttribute("type", "text");
pagesField.setAttribute("placeholder", "Pages");
readingStatusField.classList.add("formfield")
readingStatusField.setAttribute("type", "text");
readingStatusField.setAttribute("placeholder", "Reading Status");
submitButton.innerHTML = "Add"
submitButton.classList.add("submitButton")
submitButton.setAttribute("type", "submit");
submitButton.setAttribute("value", "Submit");
// submitButton.onclick("")
form.appendChild(submitButton);
form.appendChild(readingStatusField);
form.appendChild(pagesField);
form.appendChild(authorField);
form.appendChild(nameField);
content.appendChild(form);
}
function getInfoFromForm() {
submitButton.addEventListener('click', (e) => {
let bookName = nameField.value;
let authorName = authorField.value;
let noOfPages = pagesField.value;
let readingStatus = readingStatusField.value;
let newBook = new Book(bookName, authorName, noOfPages, readingStatus);
addBookToLibrary(newBook);
displayBooks();
nameField.value = "";
authorField.value = "";
pagesField.value = "";
readingStatusField.value = "";
content.innerHTML = ""
content.removeChild(form);
})
}
let addBookButton = document.querySelector(".addBook");
addBookButton.addEventListener("click", (e) => {
let content = document.querySelector(".content")
createBookForm();
getInfoFromForm();
deleteForm();
})
In createBookForm() function, I create a form and append it to the content div. It worked fine.
In getInfoFromForm() function, I try to get info from the form, and when submit button is clicked I want to create an Book object and store it in the myLibrary[] array.
Here things get out of hand for me.
First of all, the removeChild method doesnt work and doesn't remove the form element from the content.
Second when I try to console.log the books from myLibrary[], at first submit it shows correctly. When I try this second time, it shows the first book, second book THREE TIMES and an empty book.
WHY ISN'T removeChild removing the form element and why is cicking the submit button behaves the way it is behaving.

use elements ID to find value in object JavaScript

I'm looping through some elements by class name, and adding event listeners to them. I then grab the id of the selected element (in this case "tom"), and want to use it to find the value of "role" in the "tom" object. I'm getting undefined? can anyone help?
var highlightArea = document.getElementsByClassName('highlightArea');
for (var i = 0; i < highlightArea.length; i++) {
highlightArea[i].addEventListener("mouseover", showPopup);
highlightArea[i].addEventListener("mouseover", hidePopup);
}
function showPopup(evt) {
var tom = { title:'tom', role:'full stack man' };
var id = this.id;
var role = id.role;
console.log(role)
}
You are not selecting the elements correctly, the class is hightlightArea and you are querying highlightArea (missing a 't'), so, no elements are found (you can easily discover that by debugging or using console.log(highlightArea) that is the variable that holds the elements found.
Just because the id of an element is the same name as a var, it doesn't mean that it have the properties or attributes of the variable... So when you get the Id, you need to check which one is and then get the variable that have the same name.
Also, you are adding the same listener two times mouseover that way, just the last would work, it means just hidePopup. I changed to mouseenter and mouseleave, this way will work correctly.
After that, you will be able to achieve your needs. Below is an working example.
var highlightArea = document.getElementsByClassName('hightlightArea');
var mypopup = document.getElementById("mypopup");
var tom = { title:'tom', role:'marketing'};
var jim = { title:'jim', role:'another role'};
for (var i = 0; i < highlightArea.length; i++) {
highlightArea[i].addEventListener("mouseenter", showPopup);
highlightArea[i].addEventListener("mouseleave", hidePopup);
}
function showPopup(evt) {
let ElemId = this.id;
let role;
let title;
if (ElemId == 'tom'){
role = tom.role;
title = tom.title;
}else if (ElemId == 'jim'){
role = jim.role;
title = jim.title;
}
let iconPos = this.getBoundingClientRect();
mypopup.innerHTML = role;
mypopup.style.left = (iconPos.right + 20) + "px";
mypopup.style.top = (window.scrollY + iconPos.top - 60) + "px";
mypopup.style.display = "block";
}
function hidePopup(evt) {
mypopup.style.display = "none";
}
<div class="hightlightArea" id="jim">Div Jim</div>
<div class="hightlightArea" id="tom">Div Tom</div>
<div id="mypopup"></div>
in your function 'showPopup' you have this:
var id = this.id
but this.id is not defined. You probably meant to write this:
var title = dom.title;

hide the form after button form pressed javascript

Ok, here is the thing.
I have posted 2 days in a row and you guys have helped me a lot! And know I am almost done with the project, only a few things left, and a will ask another question later here.
But to the point!
I am trying to use the .style.display = ... in my javascript and it doesnt work.
I dont know if the function isnt calling or if I have done it all wrong?
What I am trying to accomplish is that when I press the button "newButton" I got a form field, and after I am finished with the form I press the button "addContact" that is created with the form all dynamically with javascript I want the form to hide. How can I do that?
The form is not gonna submit to a php and that is why a have button and not submit, because the form is gonna display at the HTML (DOM) and show like a contactlist.
Hope you could help me out!
Here is the code.
//Contactlist funktion
function Contact(fname, lname, address, email, phone) {
this.fname = fname;
this.lname = lname;
this.address = address;
this.email = email;
this.phone = phone;
}
//The contacts
var contacts = [];
var ul1 = document.createElement('ul');
ul1.id = ('nav');
// Appending the objects
function theContacts() {
var body = document.getElementsByTagName('body')[0],
length = contacts.length;
for (var i = 0; i < length; i++) {
var cont = contacts[i],
li = document.createElement('li'),
ul = document.createElement('ul');
li.innerHTML = cont.fname + ' ' + cont.lname;
for (var key in cont) {
var info = document.createElement('li');
info.className = key;
info.innerHTML = cont[key];
ul.appendChild(info);
}
li.appendChild(ul); ul1.appendChild(li);
}
body.appendChild(ul1);
}
// Calling the object
function addForms(){
var body = document.getElementsByTagName('body')[0]
var form = document.createElement("form");
form.id = 'formList';
var myArray = ['fnameValue', 'lnameValue', 'addressValue', 'emailValue', 'phoneValue'];
var texts = ['First Name: ', 'Last Name: ', 'Address: ', 'Email: ', 'Phone: '];
// Create a loop of 5
for(var i = 0; i < 5; i++){
var input = document.createElement('input');
var newlabel = document.createElement('label');
newlabel.innerHTML = texts[i];
form.appendChild(newlabel);
input.setAttribute('type','text');
input.setAttribute('id', myArray[i]);
// adds the input's to the form.
form.appendChild(input);
}
// adds the forms to the body
body.appendChild(form);
// Add Contact Button
var addContact = document.createElement('input')
addContact.setAttribute('type', 'button')
addContact.setAttribute('id', 'addContact')
addContact.addEventListener('click', onClick);
addContact.setAttribute('value', 'Add Contact')
form.appendChild(addContact);
/* var knapp = document.getElementById('addContact');
knapp.addEventListener('click', addNewContact) */
}
function addNewContact() {
var input1 = document.getElementById('fnameValue').value;
var input2 = document.getElementById('lnameValue').value;
var input3 = document.getElementById('addressValue').value;
var input4 = document.getElementById('emailValue').value;
var input5 = document.getElementById('phoneValue').value;
contacts.length = 0;
contacts.push(new Contact(input1, input2, input3, input4, input5));
}
// Knappning för ny kontakt
var button = document.getElementById("newButton");
button.addEventListener("click", addForms);
Here is the last part of the code that I am trying to apply but doesnt work for me...
function onClick() {
var div = document.getElementById('formlist');
if (addForms.style.display !== 'none') {
addForms.style.display = 'none';
}
else {
addForms.style.display = 'block';
}
};
Here you have an JS FIDDLE for example: http://jsfiddle.net/192ds38a/
That one shows how it works now withuot the "onClick" function.
But what I want is to hide the form when the AddContact button is pressed. That button is now made to add the information to the objects, but I also want that to hide the form.
Simply add a document.getElementById("formList").remove()to the addNewContact function as you can see in http://jsfiddle.net/192ds38a/1/ . Or does this not meet your needs?

How to find the number of form elements that are getting passed to e.parameter in GAS?

In Google App Scripts (GAS), I want to be able to add and remove TextBox and TextArea elements to a FlexTable (that's being used as a form) and not worry about how many there are. I've named the text elements based on a counter to make this process easier.
So, is there a way to get the number of inputs (TextBox + TextArea) passed to e.parameter after the form is submitted?
Here's the relevant code from the FlexTable:
function doGet() {
var app = UiApp.createApplication();
var flex = app.createFlexTable().setId('myFlex');
var counter = 0;
var row_counter = 0;
...
var firstnameLabel = app.createLabel('Your FIRST Name');
var firstnameTextBox = app.createTextBox().setWidth(sm_width).setName('input' + counter).setText(data[counter]);
flex.setWidget(row_counter, 1, firstnameLabel);
flex.setWidget(row_counter, 2, firstnameTextBox);
row_counter++;
counter++;
var lastnameLabel = app.createLabel('Your LAST Name');
var lastnameTextBox = app.createTextBox().setWidth(sm_width).setName('input' + counter).setText(data[counter]);
flex.setWidget(row_counter, 1, lastnameLabel);
flex.setWidget(row_counter, 2, lastnameTextBox);
row_counter++;
counter++;
...
var submitButton = app.createButton('Submit Proposal');
flex.setWidget(row_counter, 2, submitButton);
var handler = app.createServerClickHandler('saveProposal');
handler.addCallbackElement(flex);
submitButton.addClickHandler(handler);
var scroll = app.createScrollPanel().setSize('100%', '100%');
scroll.add(flex);
app.add(scroll);
return app;
}
And here's the code for the ClickHandler (notice that I currently have 39 elements in my FlexTable):
function saveProposal(e){
var app = UiApp.getActiveApplication();
var userData = [];
var counter = 39;
for(var i = 0; i < counter; i++) {
var input_name = 'input' + i;
userData[i] = e.parameter[input_name];
}
So, is there a way to get the number of elements (in this case 39) without manually counting them and assigning this value to a variable?
I'm new at this stuff and I'd appreciate your help.
Cheers!
The simplest way is to add a hidden widget in your doGet() function that will hold the counter value like this :
var hidden = app.createHidden('counterValue',counter);// don't forget to add this widget as a callBackElement to your handler variable (handler.addCallBackElement(hidden))
then in the handler function simply use
var counter = Number(e.parameter.counterValue);// because the returned value is actually a string, as almost any other widget...
If you want to see this value while debugging you can replace it momentarily with a textBox...
You can search for arguments array based object.
function foo(x) {
console.log(arguments.length); // This will print 7.
}
foo(1,2,3,4,5,6,7) // Sending 7 parameters to function.
You could use a while loop.
var i = 0;
var userData = [];
while (e.parameter['input' + i] != undefined) {
userData[i] = e.parameter['input' + i];
i++;
};
OR:
var i = 0;
var userData = [];
var input_name = 'input0';
while (e.parameter[input_name] != undefined) {
userData[i] = e.parameter[input_name];
i++;
input_name = 'input' + i;
};

Why can only newest button work ? I find that other button's onclick function is null

function B(sName) {
this.name = sName;
}
B.prototype = {
instanceCreatButtonCount: 0,
funA: function () { // alert instance's name
alert(this.name);
},
funB: function () { // create a button which clikced can alert this instance's name through funA;
var that = this;
B.prototype.instanceCreatButtonCount++;
var id = "_id" + that.instanceCreatButtonCount;
var str = "<button id='" + id + "' >clike me</button>";
var a = document.getElementById("btns");
a.innerHTML += str;
var btn = document.getElementById(id);
btn.onclick = function () {
that.funA();
};
}
};
var b1 = new B("Jim");
var divB1 = document.getElementById("b1");
divB1.onclick = function () {
b1.funB();
}
var b2 = new B("Dad");
var divB2 = document.getElementById("b2");
divB2.onclick = function () {
b2.funB();
}
After I click divB1, I create a button through b1.funB().
After I click divB2, I create a button througb b2.funB().
Why can only newest button alert name ? I find that other button's onclick function is null.
When you use a.innerHTML += str to append a new element, the entire subtree of a gets removed before the new elements are added again; the removal also unbinds any events you have added before.
It's better to use proper DOM functions in this case, i.e. var btn = document.createElement(), etc. and a.appendChild(btn).
Fiddle provided by #ShadowWizard: http://jsfiddle.net/qR6e8/

Categories