Making a basic Javascript calculator - javascript

jsfiddle demo
Bear with me, total newb here.
I'm trying to make a simple multiplication calculator, as a experimentation with Javascript.
The catch is that -
No libraries, just pure javascript.
Javascript must be unobtrusive.
Now, the problem arises, that it doesn't give the value out.
When I do this locally, answer has a value of NaN, and if you hit Submit it stays that way, BUT, if you press the back button, you see the actual result.
In the JSFiddle, much is not shown, except for the fact that it simply doesn't work.
Please tell me, is it even possible to make an unobtrusive calculator? How?
(PS. I was taking a bit of help from sciencebuddies, just to see basic syntax and stuff, but I found it can't be done without code being obtrusive)

I realize you're probably just getting started and don't know what to include, remove, and whatnot. But, good advice here, clearly label your elements so you can understand them, and pare it down to the smallest possible code you need for it to work (even less, so you can build it up).
Here is your code reworked:
HTML
<div>
<input type="text" id="multiplicand" value="4">
<input type="text" id="multiplier" value="10">
<button type="button" id="multiply">Multiply</button>
</div>
<p id="result">
The product is: <span id="product"> </span>
</p>
Javascript
window.onload = function(){
var button = el('multiply'),
multiplicand = el('multiplicand'),
multiplier = el('multiplier'),
product = el('product');
function el(id) {
return document.getElementById(id);
};
function multiply() {
var x = parseFloat(multiplicand.value) || 0,
y = parseFloat(multiplier.value) || 0;
product.innerHTML = x * y;
}
button.onclick = multiply;
};
http://jsfiddle.net/userdude/EptAN/6/
A slightly more sophisticated approach, with add/subtract/multiply/divide:
http://jsfiddle.net/userdude/EptAN/9/

You have to change the submit button so that it doesn't submit the form. Right now clicking "Submit" causes the form submits to the same page which involves a page reload.
Change the <input type="submit" id="submitt"> to <button type=button> and it should work.
You can probably do without the <form> element in the first place. That'll stop clicking enter in your text input from reloading the page.

Your example has a couple of problems:
The form still submits. After the JS changes the value, the submit will cause the page to reload, and that work you've done setting the answer value is wasted.
You're trying to do this stuff right away. In the header, none of the body has been parsed yet (and thus, the form elements don't even exist). You'll want to wait til the page is loaded.
The script hijacks window.onload. If you don't have any other scripts on the page, that's fine...but the whole point of unobtrusive JS (IMO) is that nothing breaks whether the script is there or not.
Fixed, we have something kinda like:
// Wrap this onload in an IIFE that we pass the old onload to, so we can
// let it run too (rather than just replacing it)
(function(old_onload) {
// attach this code to onload, so it'll run after everything exists
window.onload = function(event) {
// run the previous onload
if (old_onload) old_onload.call(window, event);
document.getElementById('Xintox').onsubmit = function() {
var multiplier = +this.multiplier.value;
var multiplicand = +this.multiplicand.value;
this.answer.value = multiplier * multiplicand;
return false; // keep the form from submitting
};
};​
})(window.onload);
Note i'm attaching the meat code to the form, rather than the button, because hitting Enter in either of the factor boxes will trigger a submit as well. You could still attach to the button if you wanted, and just add a submit handler that returns false. But IMO it's better this way -- that way the form works just the same with JS as without (assuming the script on the server fills in the boxes appropriately), except it won't require a round trip to the server.

Related

jQuery form input field present even before document.ready function is called

I am facing a weird issue. I am relatively new to JavaScript jQuery.
When I refresh the page the address input field doesn't get cleared, while zip code and email fields do get cleared.
I tried $('#input_address').get(0).value='';
which clears the field. But I don't want it to happen when the user comes back from page 2 to page 1. Only on refresh should the fields be cleared.
The email and zip code works perfectly in both scenarios: refresh page and page2 to page1 navigation.
$(document).ready(function() {
console.log("doc ready function");
// $('#input_address').get(0).value='';
// togglePlaceholder($('#input_email').get(0));
// togglePlaceholder($('#input_zip').get(0));
togglePlaceholder($('#input_address').get(0));
$('input, select, textarea').each(
function() {
var val = $(this).val().trim();
if (val.length) {
$(this).addClass('sample');
}
});
$('input, select, textarea').blur(function() {
if ($(this).val())
$(this).addClass('sample');
else
$(this).removeClass('sample');
});
$('input, select, textarea').focus(function() {
console.log("focused");
if ($(this).val() == '') {
$(this).removeClass('invalid');
$(this).addClass('sample');
}
});
})
function togglePlaceholder(inputElement) {
var inputAttr = inputElement.getAttribute("placeholder");
inputElement.placeholder = "";
inputElement.onblur = function() {
this.placeholder = "";
}
inputElement.onfocus = function() {
this.placeholder = inputAttr;
}
}
.sample ~ label {
font-size: 1em;
top: -10px;
left: 0;
font-size: 1em;
color: #F47B20;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="input-field col s6 col-xs-12">
<input type="text" onblur="togglePlaceholder(this);" onfocus="togglePlaceholder(this);" placeholder="123 Example Street" id="input_address" />
<label for="input_address">Street Address</label>
</div>
So... you have two problems.
(1) Auto-completion is what refills the widgets automatically,
(2) You need to know what button was clicked to react accordingly.
Auto-Completion
In regard to the auto-completion, it most certainly happens right after the first set of scripts ran within the jQuery ready() function.
There are two ways to remove auto-completion, but really, I do not recommend either one, although I would imagine that you'll need to if your requirements are set in stones...
(a) Ask for the input widget to not even autocomplete
<input ... autocomplete="off" .../>
(b) Run your script with a timer so it happens after the auto-completion. Instead of initializing in the ready() function, you initialize in a sub-function that runs after a timer times out.
$(document).ready(function() {
setTimeout(function(){
// ...put your initialization here...
// the autocompletion data should have been taken care of at this point
}, 0);
});
Note that you can use a number large than 0 for the timeout delay, but in most cases 0 will work just fine to run the sub-function after releasing the current thread once and thus given the system time to work on the auto-completion and then call your function. With 0 it should be so fast that you should not even see the <input .../> tag flash.
Side note: you may also want to place the inner function in an actual function as in:
function init_stuff()
{
// ...your initialization code goes here...
}
$(document).ready(function() {
setTimeout(init_stuff, 0);
});
If you expect your initialization to continue to grow, this can be a lot cleaner long term.
Which button gets clicked
The next problem is to know whether that code should run or not. So you need an extra if() statement for that purpose.
There are several hacks on this stackoverflow page in that regard. However, I'm not exactly sure how you really know in the newly loaded page, that you had a Refresh or a Back button click.
From the code I see there, the loading of the page's content would 100% happen in AJAX and therefore you perfectly know which button was clicked, you just reimplemented the functionality. You'll have to search stackoverflow some more to find out how to do that. I strongly suggest that you write tests with one piece of functionality at a time to determine what is going on.
Note that will make having the initialization function separate quite useful since after reloading the page, you will be responsible to call that function (when you want the reset to happen) or not! In other words, if the Back button was clicked, load the HTML of the previous page (i.e. Page 1 in your example) and display it. Done. When clicking the Refresh button, load the HTML of the current page and call the reset function (it could also be that the Refresh is the default and you do not want to handle that button since it will anyway clear as expected.)
For a beginner, that's going to be an interesting piece of work!

How to render a new page in a javascript script

I am using XHTML, JSF and JavaScript to create a form, validate that information has been submitted into selected fields onclick in a h:commandButton, and if validated, redirect to a different page homepage.xhtml. Everything works up to the redirection, which I can't get to work.
In the JavaScript function Validation(), I have tried location="homepage.xhtml", window.location.href="homepage.xhtml", location.url="homepage.xhtml" and a few others, but nothing seems to work. I have a feeling I'm supposed to have some sort of statement which adds href="homepage.xhtml" to the h:commandButton if Validate() returns true, but I am unsure as to how to do that.
Any help is greatly appreciated. I have added the relevant code below.
Button:
<h:commandButton class="btn btn-warning" value="Continue" onclick="Validation()"/>
Validation
function Validation() {
var nameCheck = document.getElementById('formdiv:cardName');
var numCheck = document.getElementById('formdiv:cardNumber');
var expCheck = document.getElementById('formdiv:expDate');
console.log(nameCheck.value);
console.log(numCheck.value);
console.log(expCheck.value);
var variablesToCheck = [nameCheck, numCheck, expCheck];
for(i=0; i < variablesToCheck.length; i++){
if(variablesToCheck[i].value == null || variablesToCheck[i].value == ""){
alert("Fields marked with a * must be completed");
return false;
}
}
// This is where the redirection needs to go, I think...
return true;
}
EDIT: Just noticed the if else statement is incorrect logically, but syntactically it shouldn't make a difference. The else part needs to be a statement outside of the loop without a condition; this code simply tries to redirect when the field it is checking has something in, not when all fields have something in.
EDIT 2: Loop corrected
Why you need h:commandButton anyway you are using simple javascript validation
h:commandButton is rendered as <input type="submit" ../> its mission is
to submit the form so what ever javascript you are writing your form will be submitted and your page is gonna be refreshed, So If you need it this way you have to force it not to submit the form,
However from understanding your needs all you need is simple <a /> or <button /> , Or you can just add type="button" into your h:commandButton ex:<h:commandButton type="button" .../>
You can either use..
window.location.replace('Your_url'); ..
or you can use..
window.location.href= 'Your_url'; .. I guess there must be other functions too. If you want to open it in another window, like a popup, you can use.. window.open('your_url');
Hope this helps!

Div does not refresh when last character is deleted from input

I'm currently making a search function using a onkeyup="Search();" like this:
<input type="text" id="IDsearch" onkeyup="Search()" autofocus>
The function for it is:
<script type="text/javascript">
function Search() {
var inputVal = $('#IDsearch').val();
$.post('searchTest.php', {postname: inputVal},
function (data) {
$('#IDsearch').val(data)
});
$('#divRefresh').load('searchTest.php');
}
</script>
Yes, I am using the same file to both put the value in a php $_SESSION['value']; AND to store the new div data. That's no problem, it works, it does fine.
But when I delete my last character from my search box, I need to press backspace twice in order for my div to update.
Say I had a textbox with "a" in it. I will press backspace to update the a, and nothing will happen. Once I press backspace again, my div will update and post all the original values again.
Am I missing something obvious?
It's supposed to work the same way http://www.datatables.net/ does.
I have asked a question about this program before, but not about this issue, I hope it's not a problem.
I would go throught $("#IDsearch").keyup(function(){});
Tried your code with the function and didn't work, even with $("#divRefresh").html(theInputOfYours); The other way I mention to you works perfectly, even with backspace.
$(document).ready(function() {
$("#IDsearch").keyup(function() {
var value = $(this).val();
var posting = $.post("your_php_file.php", {val: value})
posting.done(function( data ) {
$( "#divRefresh" ).html(data);
});
});
});
The posting is a very basic example I can give, I use to go with $.ajax() function
Unfortunately, the behavior of keyup/keypress/keydown can be finicky sometimes, especially across different browsers.
A possible solution to ensure changes are tracked would be a listener that would track changes via a setInterval function that runs at an interval you specify.

Button.onclick automatically triggers, then will not trigger again

I have a script, which I'm using to try and display only one section of a webpage at a time.
function showMe(id){ clearPage(); changeDisplay(id, "block"); console.log(id)}
Currently, I'm using buttons to change which section is displayed.
var aBtn = document.getElementById("a-btn");
var otherBtn = document.getElementById("other-btn");
aBtn.onclick=showMe("a-btn-section-id");
otherBtn.onclick=showMe("other-btn-section-id");
However, when I load the page, the following happens:
I see the function attached to each button activate once in sequence in the console.
The page refuses to respond to further button inputs.
Testing with the console shows that showMe() and the functions it calls still all work properly. I'm sure I'm making a very basic, beginner mistake (which, hopefully, is why I can't find this problem when I Google/search StackOverflow/read event handling docs), but I'm at a loss for what that mistake is. Why would my script assume my buttons are clicked on load, and why won't it let me click them again?
You're calling the function an assign the value to onclick property instead of attach the function, try defining your onclick property as:
aBtn.onclick=function(){showMe("a-btn-section-id");};
otherBtn.onclick=function(){showMe("other-btn-section-id");};
Try the follow jsfiddle:
function showMe(id){ // some stuff..
console.log(id)
}
var aBtn = document.getElementById("a-btn");
var otherBtn = document.getElementById("other-btn");
aBtn.onclick=function(){showMe("a-btn-section-id");};
otherBtn.onclick=function(){showMe("other-btn-section-id");};
<input type="button" value="a-btn" id="a-btn"/>
<input type="button" value="other-btn" id="other-btn"/>
Hope this helps,

What can cause form buttons to fail in firefox?

I have some form buttons
<input type="button" onclick="send_away('700302','update_item','0',2)" value="Change Quantity">
and they are calling the functions below: (different buttons call different functions from this script, which is embedded in the HTML file.
<script language="javascript" type="text/javascript">
function send_away(item_c,request_c,change_item_c,quantity_c){
form_c.item.value = item_c;
form_c.request.value = request_c;
form_c.change_item.value = change_item_c;
form_c.quantity.value = quantity_c;
form_c.submit();
}
//sends the form later
function later(){
address.incoming_address.value = 'l';
address.submit();
}
function address_now(){
form_c.incoming_address.value = 'n';
form_c.submit();
}
function remove_item(item_num){
form_c.removal.value = item_num;
form_c.submit();
}
</script>
The problem is, not one of these buttons works in firefox. They all work in every other browser I've tried.
Has anyone run into this kind of problem / know what I could be doing wrong? I've stared at it for a while and can't see anything, other than that my HTML doesn't validate very well, I don't have nearly time to fix all the validation problems though.
You can see the effect at http://www.terra-cotta-pendants.com/ - click a product and add it to cart - the buttons are on the cart page.
Thanks for any help.
add id="form_c" to your form and use document.getElementById('form_c') instead of just form_c
another option would be to access the form by using document.forms.form_c, but I have always preferred using id's

Categories