Variable value not accumulating? - javascript

Hey I'm very new to JS but cannot figure out why the 3 variables at the top aren't accumulating?
var xe = 0;
var reckon = 0;
var books = 0;
document.getElementById('#go').addEventListener('click', function(){
questionOne();
});
document.getElementById('#macos').addEventListener('click',function(){
addXe();
questionThree();
});
document.getElementById('#windows').addEventListener('click',function(){
questionThree();
});
document.getElementById('#linux').addEventListener('click', function(){
questionThree();
});
document.getElementById('#large').addEventListener('click', function(){
questionFour();
addXe();
});
function addXe(){
xe++;
};
function addReckon(){
reckon++;
};
function addBooks(){
books++;
};
The rest of the code is simply a series of functions that toggles divs display on and off.
If Ive missed and important info out let me know,
Thanks!
EDIT:
github.com/daffron/accountingsoftware
I thought it would be easier to attach the whole site, the problem is each time the addXero function is executed , it doesn't accumulate the value of var xero, I have it printing to console in the other functions. Thanks –

Your parameters for document.getElementById() are wrong.
If your HTML code for a button is like this:
<input type="button" id="go" />
<!-- OR like this: -->
<button id="go" ></button>
Then your javascript code must access the button using the method getElementById() as:
document.getElementById("go");
So, one of your functions will be like:
document.getElementById('go').addEventListener('click', function(){
questionOne();
});
BUT, if you've used '#go' because you were referring to a CSS Selector then you've to use querySelector method instead of getElementByIdas:
document.querySelector("#go");
So, a function call as per your code will be:
document.querySelector('#go').addEventListener('click', function(){
questionOne();
});

you should have html label example
<label id="xeLbl">test</label>
and after changing value you should apply it to html label.
function addXe(){
xe++;
document.getElementById('xeLbl').innerHTML = xe;
};

Related

Variable doesn't update after having event listener

I cannot update the value for userPickColor for some reason, it is always undefined. But I try to console.log inside the functions and my values are actually changing. But for some reasons, once I call it outside the function, it doesn't update at all.
I'm still new to Javascript so Please Help me
Here is my code:
var white = document.getElementById("white");
var black = document.getElementById("black");
var userPickColor;
white.addEventListener("click", whiteshirt);
black.addEventListener("click", blackshirt);
function whiteshirt(){
userPickColor= "white";
}
function blackshirt(){
userPickColor= "black";
}
ShirtDescrp.innerHTML = userPickColor;
As others have said, you need to place the line that updates the .innerHTML inside of the callback functions so that after the variable has been updated, you can update the page with the most current variable value as well.
But, taking this one step further... There is a common coding methodology called DRY (Don't Repeat Yourself) and you've got two callback functions that largely do the same thing. The only difference is the actual text that gets set. Those two functions run when one of two elements on your page get clicked and those two elements have the text you want to use as their ids. We could easily combine the two callbacks into just one like this:
var ShirtDescrp = document.getElementById("des");
// There's nothing wrong with variables if they help you read the code
// more easily, but if you won't be using the value they store more than
// once, they don't really add much.
document.getElementById("white").addEventListener("click", changeColor);
document.getElementById("black").addEventListener("click", changeColor);
function changeColor() {
// No variable needed. Just set the text to the id of the element that got clicked
// "this" here refers to the object that initiated the call for the current function
// which will be one of the two buttons.
ShirtDescrp.innerHTML = this.id;
}
<button id="white">white</button>
<button id="black">black</button>
<p id="des"></p>
you have to put ShirtDescrp.innerHTML = userPickColor; inside your event listener as well since you change the variable but you didn't tell the dom to update the content
You should update the DOM same as the variable:
var white = document.getElementById("white");
var black = document.getElementById("black");
var ShirtDescrp = document.getElementById("des");
var userPickColor = null;
white.addEventListener("click", whiteshirt);
black.addEventListener("click", blackshirt);
function whiteshirt() {
userPickColor = "white";
ShirtDescrp.innerHTML = userPickColor;
}
function blackshirt() {
userPickColor = "black";
ShirtDescrp.innerHTML = userPickColor;
}
<button id="white">white</button>
<button id="black">black</button>
<p id="des"></p>
You have already got your answer... Change doesn't affect as update is not happening inside event listener. This is just a recommendation how I would do it (especially if i had more color options):
<p id="color-name">none</p>
<div class="color-buttons">
<button id="white">White</button>
<button id="black">Black</button>
<button id="orange">Orange</button>
<button id="blue">Blue</button>
<button id="green">Green</button>
<button id="red">Red</button>
</div>
JavaScript like:
var buttons = document.querySelectorAll(".color-buttons button");
var color_name = document.getElementById("color-name");
buttons.forEach(function(btn){
btn.addEventListener("click", function(){
color_name.style.background=this.id;
color_name.innerHTML=this.id;
});
});
Here is the fiddle to play around.
I would also probably generate those buttons dynamically as well. And also wouldn't use id to store color but i would use something else like data-color='red' for example.

Do I need to create multiple functions for multiple actions or can they all be housed in the same function?

I'm working on a script to simulate a page change in a Questionnaire I'm building. I figured maybe I could use a bunch of "if" statements to house all the logic but it's not working right, before I go and create separate functions I'd like to know if it's possible to put them all in one single function.
So far this is the script
function pageChange(){
var chng1 = document.getElementById("p1next");
var chng2a = document.getElementById("p2back");
var chng2b = document.getElementById("p2next");
var chng3a = document.getElementById("p3back");
var chng3b = document.getElementById("p3next");
var pg1 = document.getElementById("page01");
var pg2 = document.getElementById("page02");
var pg3 = document.getElementById("page03");
if (chng1.click){
pg1.style.display="none";
pg2.style.display="block";
}
if (chng2a.click){
pg1.style.display="block";
pg2.style.display="none";
}
the "p1next, p2back, p2next etc." are IDs I gave the buttons on the pages, which I have in DIVs that I respectively named "page01, page02, page03 etc."
Without the 2nd if statement the script works exactly how I want it, it changes the display for "page01" to none and the div for "page02" to block. When I add the second if statement it doesn't work.
The reason I want to do it like this rather than making actual pages is because I don't want the data to get lost when they load another page. Am I on the right track or do I need to create a new function for each page?
Not exactly on the right track, you should use onclick events, instead of if (x.click) like this:
var chng1 = document.getElementById("p1next");
var pg1 = document.getElementById("page01");
var pg2 = document.getElementById("page02");
// Events
chng1.onclick = function(){
pg1.style.display="none";
pg2.style.display="block";
};
This will save your function until the element is clicked and then execute that function. In your case, it is executed on page load, and at that moment the user is not clicking anything.
Why not try something like this:
HTML:
<div class="page" data-pg="1">...</div>
<div class="page" data-pg="2">...</div>
<div class="page" data-pg="3">...</div>
<input id="btnPrev" type="button" value="Prev" />
<input id="btnNext" type="button" value="Next" />
jQuery:
var pageNum = 1;
$(document).ready(function () {
$("#btnPrev").on("click", function () { ChangePage(-1); });
$("#btnNext").on("click", function () { ChangePage(1); });
ChangePage(0);
});
function ChangePage(p) {
$(".page").hide();
pageNum += p;
$(".page[data-pg='" + p + "']").show();
$("#btnPrev").removeAttr("disabled");
$("#btnNext").removeAttr("disabled");
if (pageNum === 1) $("#btnPrev").attr("disabled", "disabled");
if (pageNum === $(".page").length) $("#btnNext").attr("disabled", "disabled");
}
That way you can easily grow your number of pages without changing the script. My apologies by the way for doing this in jQuery.
Update:
Have a lot of time on my hands today and have not coded for while using vanilla Javascript. Here's the version of the code using plain js: https://jsfiddle.net/hhnbz9p2/

Can't bind event to element, created by script

I'm learning a pure JavaScript. Currently I'm exploring DOM objects, like WINDOW, DOCUMENT, ELEMENT and so on ...
I'm creating text fields on a fly and want to bind function to each element's event (onfocus or onblur for example), and pass self element as argument (like 'this').
The following script creates text field and binds it to a specific function.
var txt= document.createElement("input");
txt.type="text";
txt.value='0';
txt.size=12;
txt.style.textAlign="right";
txt.id="txt_"+self.count;
txt.addEventListener('focus', txt_focus(txt));
txt.addEventListener('blur', txt_blur(txt));
And below is the functions:
function txt_focus(txt){
txt.value=txt.id;
txt.style.backgroundColor='yellow';
}
function txt_blur(txt){
txt.style.backgroundColor='white';
}
This function recognizes given argument as element and sets its ID to value attribute, but it not affects to background color.
What have I missed?
Here is the entire HTML code:
<html>
<head>
<script type="text/javascript">
self.count =0;
function txt_focus(txt){
txt.value=txt.id;
txt.style.backgroundColor='yellow';
}
function txt_blur(txt){
txt.style.backgroundColor='white';
}
function removeGroup(){
if (self.count<1) {return;}
var parent=document.getElementById("myDiv");
var fs_x =document.getElementById('fs_'+self.count);
parent.removeChild(fs_x);
self.count--;
}
function addGroup(){
if (self.count>11) {return;}
self.count++;
var parent=document.getElementById("myDiv");
var fs=document.createElement("fieldSet");
fs.style.borderRadius="7px";
fs.style.height="45px";
fs.id='fs_'+self.count;
var l=document.createElement("legend");
l.innerHTML="interval_"+self.count;
l.style.color="darkgreen";
l.style.fontStyle="italic";
fs.appendChild(l);
var d1= document.createElement("input");
d1.type="date";
d1.value='2014-05-01';
d1.id='d1_'+self.count;
fs.appendChild(d1);
var d2= document.createElement("input");
d2.type="date";
d2.value='2014-05-22';
d2.id='d2_'+self.count;
fs.appendChild(d2);
var txt= document.createElement("input");
txt.type="text";
txt.value='0';
txt.size=12;
txt.style.textAlign="right";
txt.id="txt_"+self.count;
txt.addEventListener('focus', txt_focus(txt));
txt.addEventListener('blur', txt_blur(txt));
fs.appendChild(txt);
parent.appendChild(fs);
fs.scrollIntoView();
}
</script>
</head>
<body>
<input type="hidden" id="hd1" value="0"> </input>
<button onclick="addGroup();"> Add a group</button>
<button onclick="removeGroup();"> Remove a group</button>
<div id="myDiv" style="padding:7px;position:relative;margin-top:15px;width:500px;height:500px;background-color:#ccbbcc;overflow-y:auto;border:1px red solid;border-radius:15px;">
</div>
</body>
</html>
Solution is desired in pure JavaScript, but JQuery solution is also interesting.
My second question is:
I've some background of basic JavaScript (like Math, strings, functions, arrays, classes and so on), and there I want your advice: Is there any necessity to dig deep into JavaScript details instead of jump to a JQuery?
The issue here is the difference between referencing a function and calling it. Whenever you add the parenthesis you call the function and return the result, and the default result is undefined.
In an event handler you want to reference the function only
txt.addEventListener('focus', txt_focus);
If you have to pass arguments, you'd use an anonymous function
txt.addEventListener('focus', function() {
txt_focus(txt);
});
but here that doesn't make sense, as you're passing the element, which you could access with this inside the function instead
txt.addEventListener('focus', txt_focus);
function txt_focus() {
var txt = this; // the element
}

Add Event Listeners via an Array and FOR Loop

Been having a bit of a problem for the last couple of days. I'm trying to streamline my code as much as possible and I have now got to the stage where I am trying to add Event Listeners via JavaScript so my HTML looks tidier.
-HTML Segment-
<input type="button" id="googleSearchButton" />
<input type="button" id="youtubeSearchButton" />
<input type="button" id="wikiSearchButton" />
<input type="button" id="facebookSearchButton" />
<input type="button" id="twitterSearchButton" />
<input type="button" id="tumblrSearchButton" />
<input type="button" id="dropboxSearchButton" />
JavaScript Segment
var contIDArray = ["google", "youtube", "wiki", "facebook", "twitter", "tumblr", "dropbox"];
window.load = initAll();
function initAll(){
applyProperties();
}
function applyProperties(){
for (var i = 0; i < contIDArray.length; i++){
addEventListeners(contIDArray[i] + "SearchButton");
}
}
function addEventListeners(id){
document.getElementById(id).addEventListener("click", testAlert(id), false);
}
function testAlert(id){
alert(id + " clicked")
}
The Theory
As, I hope, you can see, the FOR loop will loop until it runs out of values in the container Array. Each time it will output the place in the Array followed by "SearchButton". For example, the first time it loops it will output "googleSearchButton", the second time "youtubeSearchButton" and so forth.
Now, I know that the FOR loop works for applying properties because I use it to apply Button values and text box placeholder text in other segments of my project.
I have made it add a simple test function ("testAlert()") and set it to pass the id of the element that called it. I have set it up so once the event listeners have been added I can simply click on each button and it will alert its id and tell me that it has been clicked.
The Problem
Now, theoretically, I thought this would work. But it seems that the FOR loops fires the "addEventListeners" function, which, in turn, adds the event listener to fire "testAlert" on click. But it just fires the "testAlert" function as soon as it adds the event listener and does not fire when you click.
I apologise if this seems a bit much to take in, I always overdo the length of my explanation. Hopefully you'll be able to see what I'm trying to accomplish from my code, rather than my explanation.
Help would be much appreciated. :)
You're close here, but there are a few things wrong.
First, you can't just do id.addEventListener. You need to do document.getElementById(id).addEventListener. id is just a string, you need a DOMElement.
Second, when you do testAlert(id), you're running the function, then assigning its return value (undefined) as the event listener. You need to pass a function. Like so:
id.addEventListener("click", function(){
testAlert(this.id); // this is the DOMElement you clicked on
}, false);
Though I suggest adding a class to all your buttons, and then adding the event like that.
<input type="button" id="googleSearchButton" class="searchButton" />
<input type="button" id="youtubeSearchButton" class="searchButton" />
<input type="button" id="wikiSearchButton" class="searchButton" />
<input type="button" id="facebookSearchButton" class="searchButton" />
<input type="button" id="twitterSearchButton" class="searchButton" />
<input type="button" id="tumblrSearchButton" class="searchButton" />
<input type="button" id="dropboxSearchButton" class="searchButton" />
And then:
var buttons = document.getElementsByClassName('searchButton');
for(b in buttons){
if(buttons.hasOwnProperty(b)){
buttons[b].addEventListener("click", function(){
testAlert(this.id); // this is the DOMElement you clicked on
}, false);
}
}
NOTE: addEventListener and getElementsByClassName may not be available in all browsers (by that I mean they might not work in IE). This is why a lot of websites use a JavaScript library, like jQuery. jQuery handles all the cross-browser stuff for you. If you want to use jQuery, you could do this:
$('.searchButton').click(function(){
testAlert(this.id);
});
NOTE 2: In JavaScript, functions are variables, and can be passed as parameters.
document.getElementById(id).addEventListener('click', testAlert, false);
Notice how there are no () after testAlert, we are passing the function itself, when you do testAlert() you're passing its return value. If you do it this way, testAlert will need to be modified a bit:
function testAlert(){
alert(this.id + " clicked")
}
Change:
function addEventListeners(id){
id.addEventListener("click", testAlert(id), false);
}
for:
function addEventListeners(id){
document.getElementById(id).addEventListener("click", testAlert(id), false);
}
Otherwise you're applying addEventListener on a string.
In any case, replace addEventListener with an assignment to the event, like onClick.
id looks like a string to me. So instead do something like this:
function addEventListeners(id){
var obj = document.getElementById(id);
obj.addEventListener("click", testAlert(id), false);
}
Also, here is the working code:
http://jsfiddle.net/ZRZY9/2/
obj.addEventListener("click", function() { testAlert(id); }, true);
As Rocket mentions above "you're calling it and setting the event to the return value undefined".
The bad news is addEventListener() is currently not supported in Internet Explorer 7.
I ran through your code. The initial problem that I came across was that you were trying to find the elements in the document before they were created. window.onLoad fires before the page is complete. I tested this using the body tag's onload attribute and it works that way.
So, it's a combination of the aforementioned issue of your trying to find the element by using the "id" string and the function firing before the page was completely loaded.
Anyway, glad you got it working!
This is the javascript I had at the end:
<script>
var contIDArray = ["google", "youtube", "wiki", "facebook", "twitter", "tumblr", "dropbox"];
function initAll(){
applyProperties();
}
function applyProperties(){
for (var i = 0; i < contIDArray.length; i++){
var newString = contIDArray[i] + "SearchButton"
addEventListeners(newString);
}
}
function addEventListeners(id){
document.getElementById(id).addEventListener("click", testAlert, false);
}
function testAlert(){
alert(this.id + " clicked")
}
</script>

how to get outerHTML with jquery in order to have it cross-browser

I found a response in a jquery forum and they made a function to do this but the result is not the same.
Here is an example that I created for an image button:
var buttonField = $('<input type="image" />');
buttonField.attr('id', 'butonFshi' + lastsel);
buttonField.val('Fshi');
buttonField.attr('src', 'images/square-icon.png');
if (disabled)
buttonField.attr("disabled", "disabled");
buttonField.val('Fshi');
if (onblur !== undefined)
buttonField.focusout(function () { onblur(); });
buttonField.mouseover(function () { ndryshoImazhin(1, lastsel.toString()); });
buttonField.mouseout(function () { ndryshoImazhin(0, lastsel.toString()); });
buttonField.click(function () { fshiClicked(lastsel.toString()); });
And I have this situation:
buttonField[0].outerHTML = `<INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image jQuery15205073038169030395="44">`
instead the outer function I found gives buttonField.outer() = <INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image>
The function is:
$.fn.outer = function(val){
if(val){
$(val).insertBefore(this);
$(this).remove();
}
else{ return $("<div>").append($(this).clone()).html(); }
}
so like this I loose the handlers that I inserted.
Is there anyway to get the outerHTML with jquery in order to have it cross-browser without loosing the handlers ?!
You don't need convert it to text first (which is what disconnects it from the handlers, only DOM nodes and other specific JavaScript objects can have events). Just insert the newly created/modified node directly, e.g.
$('#old-button').after(buttonField).remove();`
after returns the previous jQuery collection so the remove gets rid of the existing element, not the new one.
Try this one:
var html_text = `<INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image jQuery15205073038169030395="44">`
buttonField[0].html(html_text);
:)
Check out the jQuery plugin from https://github.com/darlesson/jquery-outerhtml. With this jQuery plugin you can get the outerHTML from the first matched element, replace a set of elements and manipulate the result in a callback function.
Consider the following HTML:
<span>My example</span>
Consider the following call:
var span = $("span").outerHTML();
The variable span is equal <span>My example</span>.
In the link above you can find more example in how to use .outerHTML() plug-in.
This should work fine:
var outer = buttonField.parent().html();

Categories

Resources